You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2141 lines
88 KiB
2141 lines
88 KiB
--[[
|
|
Extends Modules by adding:
|
|
Module:OnWindowCreated(winObj)
|
|
Module:OnWindowDestroyed(winObj)
|
|
Module:OnWindowPopped(winObj)
|
|
Module:OnWindowMessageAdded(winObj, msg, r, g, b)
|
|
Module:OnWindowShow(winObj)
|
|
Module:OnWindowHide(winObj)
|
|
Module:OnContainerShow()
|
|
Module:OnContainerHide()
|
|
]]
|
|
|
|
local WIM = WIM;
|
|
|
|
-- imports
|
|
local _G = _G;
|
|
local CreateFrame = CreateFrame;
|
|
local UIFrameFadeIn = UIFrameFadeIn;
|
|
local UIFrameFadeOut = UIFrameFadeOut;
|
|
local GetMouseFocus = GetMouseFocus;
|
|
local table = table;
|
|
local string = string;
|
|
local IsShiftKeyDown = IsShiftKeyDown;
|
|
local select = select;
|
|
local pairs = pairs;
|
|
local type = type;
|
|
local unpack = unpack;
|
|
local strsub = strsub;
|
|
local time = time;
|
|
local Ambiguate = Ambiguate;
|
|
local GetGuildInfo = GetGuildInfo;
|
|
local UnitClass = UnitClass;
|
|
local UnitLevel = UnitLevel;
|
|
local UnitRace = UnitRace;
|
|
|
|
-- set namespace
|
|
setfenv(1, WIM);
|
|
|
|
|
|
-- load message window related default settings.
|
|
db_defaults.displayColors = {
|
|
sysMsg = {
|
|
r=1,
|
|
g=0.6627450980392157,
|
|
b=0
|
|
},
|
|
errorMsg = {
|
|
r=1,
|
|
g=0,
|
|
b=0
|
|
},
|
|
useSkin = true,
|
|
};
|
|
db_defaults.fontSize = 12;
|
|
db_defaults.windowAlpha = 80;
|
|
db_defaults.windowOnTop = true;
|
|
db_defaults.keepFocus = true;
|
|
db_defaults.keepFocusRested = true;
|
|
db_defaults.autoFocus = false;
|
|
db_defaults.winSize = {
|
|
width = 333,
|
|
height = 220,
|
|
scale = 100,
|
|
strata = "DIALOG"
|
|
};
|
|
db_defaults.winLoc = {
|
|
left =217,
|
|
top =664
|
|
};
|
|
db_defaults.winCascade = {
|
|
enabled = true,
|
|
direction = 8
|
|
};
|
|
db_defaults.winFade = true;
|
|
db_defaults.winAnimation = true;
|
|
db_defaults.wordwrap_indent = false;
|
|
db_defaults.coloredNames = true;
|
|
db_defaults.escapeToHide = true;
|
|
db_defaults.ignoreArrowKeys = true;
|
|
db_defaults.pop_rules = {};
|
|
db_defaults.whoLookups = true;
|
|
db_defaults.hoverLinks = false;
|
|
db_defaults.tabAdvance = false;
|
|
db_defaults.clampToScreen = true;
|
|
|
|
db_defaults.formatting = {
|
|
bracketing = {
|
|
enabled = true,
|
|
type = 1,
|
|
},
|
|
};
|
|
|
|
|
|
WIM.lists.bracketing = {
|
|
[1] = {
|
|
[1] = "[",
|
|
[2] = "]"
|
|
},
|
|
[2] = {
|
|
[1] = "<",
|
|
[2] = ">"
|
|
},
|
|
}
|
|
|
|
local WindowSoupBowl = {
|
|
windowToken = 0,
|
|
available = 0,
|
|
used = 0,
|
|
windows = {
|
|
}
|
|
}
|
|
|
|
local FadeProps = {
|
|
min = .5,
|
|
max = 1,
|
|
interval = .25,
|
|
delay = 2
|
|
};
|
|
|
|
local cascadeDirection = {
|
|
{0, 25}, -- Up
|
|
{0, -25}, -- Down
|
|
{-50, 0}, -- Left
|
|
{50, 0}, -- Right
|
|
{-50, 25}, -- Up & Left
|
|
{50, 25}, -- Up & Right
|
|
{-50, -25}, -- Down & Left
|
|
{50, -25}, -- Down & Right
|
|
};
|
|
|
|
windowsByAge = {};
|
|
|
|
nextColor = {};
|
|
|
|
local FormattingCallsList = {}; -- used to get a list of available Formattings.
|
|
local FormattingCalls = {}; -- functions which are passed events to be formatted. Only one may be used at once.
|
|
|
|
local StringModifiers = {}; -- registered functions which will be used to format the message part of the string.
|
|
|
|
|
|
-- Window's Parent (Container for all Windows)
|
|
WindowParent = _G.CreateFrame("Frame", "WIM_UIParent", _G.UIParent);
|
|
WindowParent:SetFrameStrata("BACKGROUND");
|
|
WindowParent:SetPoint("BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", 0, 0);
|
|
WindowParent:SetScript("OnShow", function(self)
|
|
WindowParent:SetWidth(_G.UIParent:GetWidth());
|
|
WindowParent:SetHeight(_G.UIParent:GetHeight());
|
|
end);
|
|
-- WindowParent.test = WindowParent:CreateTexture("BACKGROUND");
|
|
-- WindowParent.test:SetColorTexture(1,1,1,.5)
|
|
-- WindowParent.test:SetAllPoints();
|
|
WindowParent:Hide();
|
|
|
|
|
|
-- the following table defines a list of actions to be taken when
|
|
-- script handlers are fired for different type windows.
|
|
-- use WIM:RegisterWidgetTrigger(WindowType, ScriptEvent, function());
|
|
local Widget_Triggers = {};
|
|
|
|
local function getFormatByName(format)
|
|
local i;
|
|
for i=1, #FormattingCalls do
|
|
if(FormattingCalls[i].name == format) then
|
|
return FormattingCalls[i].fun;
|
|
end
|
|
end
|
|
return FormattingCalls[1].fun;
|
|
end
|
|
|
|
function applyMessageFormatting(...)
|
|
local fun = getFormatByName(db.messageFormat);
|
|
return fun(...);
|
|
end
|
|
|
|
|
|
function applyStringModifiers(str, chatDisplay)
|
|
for i=1, #StringModifiers do
|
|
str = StringModifiers[i](str, chatDisplay);
|
|
end
|
|
chatDisplay.noEscapedStrings = nil;
|
|
return str;
|
|
end
|
|
|
|
|
|
local RegisteredWidgets = {}; -- a list of registered widgets added to windows from modules.
|
|
windows.widgets = RegisteredWidgets;
|
|
|
|
--[[ Sample Widget with triggers
|
|
RegisteredWidgets["Test"] = function(parentWindow)
|
|
_G.DEFAULT_CHAT_FRAME:AddMessage("Test Widget created!");
|
|
local t = CreateFrame("Frame");
|
|
t.SetDefaults = function()
|
|
_G.DEFAULT_CHAT_FRAME:AddMessage("Test Widget defaults set!");
|
|
end
|
|
t.UpdateProps = function()
|
|
_G.DEFAULT_CHAT_FRAME:AddMessage("Test Widget props updated!");
|
|
end
|
|
return t;
|
|
end
|
|
]]
|
|
|
|
local windowListByLevel_Recycle = {};
|
|
local function getActiveWindowListByLevel()
|
|
-- first remove items from previously used list.
|
|
local i;
|
|
for i=1,#windowListByLevel_Recycle do
|
|
table.remove(windowListByLevel_Recycle, 1);
|
|
end
|
|
-- load all used windows into table
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse and WindowSoupBowl.windows[i].obj:IsVisible()) then
|
|
table.insert(windowListByLevel_Recycle, WindowSoupBowl.windows[i].obj);
|
|
end
|
|
end
|
|
table.sort(windowListByLevel_Recycle, function(a,b)
|
|
a, b = a:GetFrameLevel(), b:GetFrameLevel();
|
|
return a>b;
|
|
end);
|
|
return windowListByLevel_Recycle;
|
|
end
|
|
|
|
function getWindowAtCursorPosition(excludeObj)
|
|
-- can optionaly exclude an object
|
|
local x,y = _G.GetCursorPosition();
|
|
local windows = getActiveWindowListByLevel();
|
|
local i;
|
|
for i=1,#windows do
|
|
if(excludeObj ~= windows[i]) then
|
|
local x1, y1 = windows[i]:GetLeft()*windows[i]:GetEffectiveScale(), windows[i]:GetTop()*windows[i]:GetEffectiveScale();
|
|
local x2, y2 = x1 + windows[i]:GetWidth()*windows[i]:GetEffectiveScale(), y1 - windows[i]:GetHeight()*windows[i]:GetEffectiveScale();
|
|
if(x >= x1 and x <= x2 and y <= y1 and y >= y2) then
|
|
return windows[i];
|
|
end
|
|
end
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
-- window resizing helper
|
|
local resizeFrame = CreateFrame("Button", "WIM_WindowResizeFrame", WindowParent);
|
|
resizeFrame:Hide();
|
|
resizeFrame.widgetName = "resize";
|
|
resizeFrame:SetFrameStrata("TOOLTIP");
|
|
resizeFrame.Attach = function(self, win)
|
|
if(win.widgets.close ~= GetMouseFocus() and win.type ~= "demo") then
|
|
self:SetParent(win);
|
|
self.parentWindow = win;
|
|
ApplySkinToWidget(self);
|
|
self:Show();
|
|
-- resizeFrame:SetFrameLevel(999);
|
|
else
|
|
self:Reset();
|
|
resizeFrame:Hide();
|
|
end
|
|
end
|
|
resizeFrame.Reset = function(self)
|
|
self:SetParent(WindowParent);
|
|
self:ClearAllPoints();
|
|
self:SetPoint("TOPLEFT");
|
|
self:Hide();
|
|
end
|
|
resizeFrame:SetScript("OnMouseDown", function(self)
|
|
self.isSizing = true;
|
|
self.parentWindow.customSize = true;
|
|
self.parentWindow:SetResizable(true);
|
|
self.parentWindow:StartSizing("BOTTOMRIGHT");
|
|
end);
|
|
resizeFrame:SetScript("OnMouseUp", function(self)
|
|
self.isSizing = false;
|
|
self.parentWindow.customSize = true;
|
|
self.parentWindow:StopMovingOrSizing();
|
|
local tabStrip = self.parentWindow.tabStrip;
|
|
if(tabStrip) then
|
|
dPrint("Size sent to tab strip.");
|
|
end
|
|
-- DisplayTutorial(L["Window Resized!"], L["If you want all windows to be this size, you can set the default window size within WIM's options."]);
|
|
end);
|
|
resizeFrame:SetScript("OnHide", function(self)
|
|
if(self.parentWindow and self.isSizing) then
|
|
local OnMouseUp = self:GetScript("OnMouseUp");
|
|
OnMouseUp(self);
|
|
end
|
|
end);
|
|
resizeFrame:SetScript("OnUpdate", function(self)
|
|
if(self.isSizing and self.parentWindow and self.parentWindow.tabStrip) then
|
|
local curSize = self.parentWindow:GetWidth()..self.parentWindow:GetHeight();
|
|
if(self.prevSize ~= curSize) then
|
|
self.parentWindow.tabStrip:UpdateTabs();
|
|
self.prevSize = curSize;
|
|
end
|
|
end
|
|
if(self.parentWindow.isMoving) then
|
|
self:Reset();
|
|
end
|
|
end);
|
|
|
|
|
|
-- helperFrame's purpose is to assist with dragging and dropping of Windows into tab strips.
|
|
-- The frame will monitor which window objects are being dragged over and attach itself to them when
|
|
-- it's key trigger is pressed.
|
|
local helperFrame = CreateFrame("Frame", "WIM_WindowHelperFrame", WindowParent);
|
|
helperFrame.flash = helperFrame:CreateTexture(helperFrame:GetName().."Flash", "OVERLAY");
|
|
helperFrame.flash:SetPoint("BOTTOMLEFT");
|
|
helperFrame.flash:SetPoint("BOTTOMRIGHT");
|
|
helperFrame.flash:SetHeight(4);
|
|
helperFrame.flash:SetBlendMode("ADD");
|
|
helperFrame.flash:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight");
|
|
helperFrame:SetFrameStrata("TOOLTIP");
|
|
helperFrame:SetWidth(1);
|
|
helperFrame:SetHeight(1);
|
|
helperFrame.ResetState = function(self)
|
|
helperFrame:ClearAllPoints();
|
|
helperFrame:SetParent(UIPanel);
|
|
helperFrame:SetWidth(1);
|
|
helperFrame:SetHeight(1);
|
|
helperFrame:SetPoint("TOPLEFT", WindowParent, "TOPLEFT", 0, 0);
|
|
helperFrame.isAttached = false;
|
|
helperFrame.attachedTo = nil;
|
|
end
|
|
helperFrame:SetPoint("TOPLEFT", WindowParent, "TOPLEFT", 0, 0);
|
|
helperFrame:SetScript("OnUpdate", function(self)
|
|
if(IsShiftKeyDown()) then
|
|
local obj = GetMouseFocus();
|
|
if(obj and (obj.isWimWindow or obj.parentWindow)) then
|
|
local win;
|
|
if(obj.isWimWindow) then
|
|
win = obj;
|
|
else
|
|
win = obj.parentWindow;
|
|
end
|
|
if(win == WIM.DemoWindow) then
|
|
return;
|
|
end
|
|
if(not win.isMoving) then
|
|
resizeFrame:Attach(win);
|
|
end
|
|
if(win.isMoving and not (win.tabStrip and win.tabStrip:IsVisible())) then
|
|
local mWin = getWindowAtCursorPosition(win);
|
|
if(mWin) then
|
|
if(self.isAttached) then
|
|
if(mWin ~= self.attachedTo) then
|
|
self:ResetState();
|
|
end
|
|
else
|
|
if(mWin ~= WIM.DemoWindow) then
|
|
-- attach to window
|
|
local skinTable = GetSelectedSkin().tab_strip;
|
|
self.parentWindow = mWin;
|
|
self.attachedTo = mWin;
|
|
mWin.helperFrame = self;
|
|
self:SetParent(mWin);
|
|
SetWidgetRect(self, skinTable);
|
|
self:SetHeight(self.flash:GetHeight());
|
|
self.isAttached = true;
|
|
end
|
|
end
|
|
else
|
|
if(self.isAttached) then
|
|
self:ResetState();
|
|
end
|
|
end
|
|
else
|
|
if(self.isAttached) then
|
|
self:ResetState();
|
|
end
|
|
end
|
|
else
|
|
resizeFrame:Reset();
|
|
if(self.isAttached) then
|
|
self:ResetState();
|
|
end
|
|
end
|
|
else
|
|
resizeFrame:Reset();
|
|
if(self.isAttached) then
|
|
self:ResetState();
|
|
end
|
|
end
|
|
if(self.isAttached) then
|
|
self.flash:Show();
|
|
else
|
|
self.flash:Hide();
|
|
end
|
|
end);
|
|
helperFrame:Show();
|
|
|
|
|
|
local function executeHandlers(WidgetName, wType, HandlerName, ...)
|
|
local tbl, fun;
|
|
if(Widget_Triggers[WidgetName] and Widget_Triggers[WidgetName][HandlerName] and Widget_Triggers[WidgetName][HandlerName][wType]) then
|
|
tbl = Widget_Triggers[WidgetName][HandlerName][wType];
|
|
end
|
|
if(type(tbl) == "table") then
|
|
for i=1,#tbl do
|
|
fun = tbl[i];
|
|
fun(...);
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Returns object, SoupBowl_windows_index or nil if window can not be found.
|
|
local function getWindowBy(userName)
|
|
if(type(userName) ~= "string") then
|
|
return nil;
|
|
end
|
|
for i=1,#WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].user == userName) then
|
|
return WindowSoupBowl.windows[i].obj, i;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
-- Clean up the frame's points and make sure the main point TOPLEFT,BOTTOMRIGHT is set
|
|
function cleanPoints(win)
|
|
local x, y;
|
|
for i = 1, win:GetNumPoints() do
|
|
local p1, parent, p2, tx, ty = win:GetPoint(i);
|
|
_G.DEFAULT_CHAT_FRAME:AddMessage(p1..", ".._G.tostring(parent)..", "..p2..", "..tx..", "..ty);
|
|
end
|
|
_G.DEFAULT_CHAT_FRAME:AddMessage(" "..win:SafeGetLeft()..", "..win:SafeGetTop());
|
|
end
|
|
|
|
-- climb up inherritance tree and find parent window recursively.
|
|
local function getParentMessageWindow(obj)
|
|
if(not obj) then
|
|
return nil;
|
|
elseif(obj.isParent) then
|
|
return obj;
|
|
elseif(obj.parentWindow) then
|
|
return obj.parentWindow;
|
|
elseif(obj:GetName() == "UIParent") then
|
|
return nil;
|
|
else
|
|
return getParentMessageWindow(obj:GetParent())
|
|
end
|
|
end
|
|
|
|
local function animateFade(obj, directionIn, force)
|
|
local fadeAnimator = obj.animators.fade
|
|
local to = directionIn and FadeProps.max or FadeProps.min
|
|
local from = obj:GetAlpha()
|
|
|
|
if force then
|
|
obj:SetAlpha(to)
|
|
fadeAnimator.animation.fadingDiretionIn = directionIn
|
|
return
|
|
end
|
|
|
|
if fadeAnimator:IsPlaying() then
|
|
local progress = fadeAnimator:GetProgress()
|
|
from = fadeAnimator.animation:GetToAlpha() * progress
|
|
fadeAnimator:Stop()
|
|
|
|
fadeAnimator.animation:SetDuration(FadeProps.interval)
|
|
fadeAnimator.animation:SetFromAlpha(from)
|
|
fadeAnimator.animation:SetToAlpha(to)
|
|
fadeAnimator:Play()
|
|
fadeAnimator:SetScript("OnFinished", function ()
|
|
obj:SetAlpha(to)
|
|
end)
|
|
else
|
|
fadeAnimator.animation:SetDuration(FadeProps.interval)
|
|
fadeAnimator.animation:SetFromAlpha(from)
|
|
fadeAnimator.animation:SetToAlpha(to)
|
|
fadeAnimator:SetScript("OnFinished", function ()
|
|
obj:SetAlpha(to)
|
|
end)
|
|
fadeAnimator:Play()
|
|
end
|
|
|
|
fadeAnimator.animation.fadingDiretionIn = directionIn
|
|
end
|
|
|
|
local function setWindowAsFadedIn(obj)
|
|
if(WIM.db.winFade) then
|
|
if not obj.fadedIn then
|
|
obj:fadeIn()
|
|
obj.delayFadeElapsed = 0;
|
|
obj.delayFade = true;
|
|
obj.fadedIn = true;
|
|
end
|
|
else
|
|
obj:fadeIn(true);
|
|
end
|
|
end
|
|
|
|
--------------------------------------
|
|
-- Widget Script Handlers --
|
|
--------------------------------------
|
|
|
|
function updateScrollBars(parentWindow)
|
|
if(parentWindow and parentWindow.widgets and parentWindow.widgets.chat_display) then
|
|
if(parentWindow.widgets.chat_display:AtTop()) then
|
|
parentWindow.widgets.scroll_up:Disable();
|
|
else
|
|
parentWindow.widgets.scroll_up:Enable();
|
|
end
|
|
if(parentWindow.widgets.chat_display:AtBottom()) then
|
|
parentWindow.widgets.scroll_down:Disable();
|
|
else
|
|
parentWindow.widgets.scroll_down:Enable();
|
|
end
|
|
end
|
|
end
|
|
|
|
local function MessageWindow_MovementControler_OnDragStart(self)
|
|
local window = getParentMessageWindow(self);
|
|
if(window) then
|
|
window:StartMoving();
|
|
window.isMoving = true;
|
|
end
|
|
end
|
|
|
|
local function MessageWindow_MovementControler_OnDragStop(self)
|
|
local window = getParentMessageWindow(self);
|
|
if(window) then
|
|
local dropTo = helperFrame.attachedTo;
|
|
helperFrame:ResetState();
|
|
window:StopMovingOrSizing();
|
|
window.isMoving = false;
|
|
window.widgets.chat_display:Hide();
|
|
window.widgets.chat_display:Show();
|
|
window.hasMoved = true;
|
|
if(dropTo) then
|
|
if(dropTo.tabStrip) then
|
|
dropTo.tabStrip:Attach(window);
|
|
window:Hide();
|
|
dropTo.tabStrip:JumpToTab(dropTo);
|
|
else
|
|
window:Hide();
|
|
local tabStrip = GetAvailableTabGroup();
|
|
tabStrip:Attach(dropTo);
|
|
tabStrip:Attach(window);
|
|
tabStrip:JumpToTab(dropTo);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- this needs to be looked at. it isn't doing anything atm...
|
|
local function MessageWindow_Frame_OnShow(self)
|
|
if(WindowParent.animUp) then
|
|
return;
|
|
end
|
|
-- _G.DEFAULT_CHAT_FRAME:AddMessage(_G.debugstack(1))
|
|
setWindowAsFadedIn(self);
|
|
if(self ~= DemoWindow) then
|
|
updateScrollBars(self);
|
|
CallModuleFunction("OnWindowShow", self);
|
|
for widgetName, widgetObj in pairs(self.widgets) do
|
|
if(type(widgetObj.OnWindowShow) == "function") then
|
|
widgetObj:OnWindowShow();
|
|
end
|
|
end
|
|
else
|
|
self.widgets.chat_display:Clear();
|
|
self.widgets.chat_display:AddMessage(L["_DemoText"]);
|
|
self.widgets.msg_box:Hide();
|
|
end
|
|
end
|
|
|
|
-- this needs to be looked at. it isn't doing anything atm...
|
|
local function MessageWindow_Frame_OnHide(self)
|
|
if ( self.isMoving ) then
|
|
self:StopMovingOrSizing();
|
|
self.isMoving = false;
|
|
end
|
|
self:ResetAnimation();
|
|
if(self.type == "demo" and self.demoSave) then
|
|
-- save window placement settings.
|
|
db.winLoc.left = self:SafeGetLeft()*self:GetEffectiveScale();
|
|
db.winLoc.top = self:SafeGetTop()*self:GetEffectiveScale();
|
|
options.frame:Enable();
|
|
self.demoSave = nil;
|
|
DestroyWindow(self);
|
|
WIM.DemoWindow = nil;
|
|
elseif(self.type ~= "demo") then
|
|
CallModuleFunction("OnWindowHide", self);
|
|
for widgetName, widgetObj in pairs(self.widgets) do
|
|
if(type(widgetObj.OnWindowHide) == "function") then
|
|
widgetObj:OnWindowHide();
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function updateTracker(win)
|
|
if(not WindowParent.animUp) then
|
|
local pS, sS = WindowParent:GetEffectiveScale(), win:GetEffectiveScale()
|
|
local pL, pR, pT, pB = WindowParent:GetLeft()*pS, WindowParent:GetRight()*pS, WindowParent:GetTop()*pS, WindowParent:GetBottom()/pS;
|
|
local sL, sR, sT, sB = win:GetLeft()*sS, win:GetRight()*sS, win:GetTop()*sS, win:GetBottom()*sS;
|
|
|
|
if(not db.clampToScreen and sT < 0) then -- bottom
|
|
if(win.offScreen ~= 1) then
|
|
win.offScreen = 1;
|
|
CallModuleFunction("OnWindowLeaveScreen", win, 1);
|
|
end
|
|
elseif(not db.clampToScreen and sB > pT) then -- top
|
|
if(win.offScreen ~= 2) then
|
|
win.offScreen = 2;
|
|
CallModuleFunction("OnWindowLeaveScreen", win, 2);
|
|
end
|
|
elseif(not db.clampToScreen and sR < 0) then -- left
|
|
if(win.offScreen ~= 3) then
|
|
win.offScreen = 3;
|
|
CallModuleFunction("OnWindowLeaveScreen", win, 3);
|
|
end
|
|
elseif(not db.clampToScreen and sL > pR) then -- right
|
|
if(win.offScreen ~= 4) then
|
|
win.offScreen = 4;
|
|
CallModuleFunction("OnWindowLeaveScreen", win, 4);
|
|
end
|
|
else
|
|
-- on screen
|
|
if(win.offScreen ~= 0) then
|
|
CallModuleFunction("OnWindowEnterScreen", win);
|
|
end
|
|
win.offScreen = 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function MessageWindow_Frame_OnUpdate(self, elapsed)
|
|
-- window is visible, there aren't any messages waiting...
|
|
updateTracker(self);
|
|
self.msgWaiting = false;
|
|
self.unreadCount = 0;
|
|
-- animation segment
|
|
if(self.animation and self.animation.mode) then
|
|
local animate = self.animation;
|
|
if(animate.mode == "HIDE") then
|
|
animate.elapsed = animate.elapsed + elapsed;
|
|
if(animate.elapsed > animate.time) then
|
|
self:Hide_Normal();
|
|
else
|
|
local prct = animate.elapsed/animate.time;
|
|
local scale = (db.winSize.scale/100)*(1-prct);
|
|
scale = scale > animate.scaleLimit and scale or animate.scaleLimit;
|
|
self:SetScale(scale);
|
|
if(animate.to and animate.to.GetEffectiveScale) then
|
|
local to = animate.to;
|
|
local es, ts = self:GetEffectiveScale(), to:GetEffectiveScale();
|
|
es, ts = es > 0 and es or .01, ts > 0 and ts or .01;
|
|
local x1, y1, x2, y2 = animate.initLeft*es, animate.initTop*es, to:GetLeft()*ts, to:GetTop()*ts;
|
|
local rise, run = ((y2-y1)>=0) and (y2-y1) or 0, ((x2-x1)>=0) and (x2-x1) or 0;
|
|
self:ClearAllPoints();
|
|
self:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", (x1+run*prct)/es, (y1+rise*prct)/es);
|
|
end
|
|
end
|
|
end
|
|
else
|
|
-- fading segment
|
|
if(db.winFade and self ~= DemoWindow) then
|
|
self.fadeElapsed = (self.fadeElapsed or 0) + elapsed;
|
|
while(self.fadeElapsed > .1) do
|
|
local window = GetMouseFocus();
|
|
if(window) then
|
|
if(((window == self or window.parentWindow == self or self.isOnHyperLink or
|
|
self == helperFrame.attachedTo or
|
|
(EditBoxInFocus and EditBoxInFocus.parentWindow == self)) or
|
|
(window.tabStrip and window.tabStrip.selected.obj == self)) and
|
|
(not self.fadedIn or self.delayFade)) then
|
|
self:fadeIn()
|
|
self.fadedIn = true;
|
|
self.delayFade = false;
|
|
self.delayFadeElapsed = 0;
|
|
elseif(window ~= self and window.parentWindow ~= self and not self.isOnHyperLink and
|
|
(not (window.tabStrip and window.tabStrip.selected.obj == self)) and
|
|
helperFrame.attachedTo ~= self and
|
|
(not EditBoxInFocus or EditBoxInFocus.parentWindow ~= self) and self.fadedIn) then
|
|
if(self.delayFade) then
|
|
self.delayFadeElapsed = (self.delayFadeElapsed or 0) + elapsed;
|
|
while(self.delayFadeElapsed > FadeProps.delay) do
|
|
self.delayFade = false;
|
|
self.delayFadeElapsed = 0;
|
|
end
|
|
else
|
|
self.fadedIn = false;
|
|
self.delayFadeElapsed = 0;
|
|
self:fadeOut()
|
|
end
|
|
end
|
|
end
|
|
self.fadeElapsed = 0;
|
|
end
|
|
elseif(not self.fadedIn) then
|
|
setWindowAsFadedIn(self);
|
|
end
|
|
end
|
|
end
|
|
|
|
-- local function MessageWindow_MsgBox_OnMouseUp()
|
|
-- CloseDropDownMenus();
|
|
-- if(arg1 == "RightButton") then
|
|
-- WIM_MSGBOX_MENU_CUR_USER = this:GetParent().theUser;
|
|
-- UIDropDownMenu_Initialize(WIM_MsgBoxMenu, WIM_MsgBoxMenu_Initialize);
|
|
-- ToggleDropDownMenu(1, nil, WIM_MsgBoxMenu, this, 0, 0);
|
|
-- end
|
|
-- end
|
|
|
|
|
|
|
|
local function loadHandlers(obj)
|
|
local widgets = obj.widgets;
|
|
for widget, tbl in pairs(Widget_Triggers) do
|
|
for handler,_ in pairs(tbl) do
|
|
-- This is, what i feel an over kill of checks.. but if it works... /shrug.
|
|
if(widgets[widget] and widgets[widget]and not widgets[widget]:GetScript(handler)) then
|
|
widgets[widget]:SetScript(handler, function(...) executeHandlers(widget, obj.type, handler, ...); end)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function setAllChildrenParentWindow(parent, child)
|
|
local i;
|
|
if(child ~= parent) then
|
|
child.parentWindow = parent;
|
|
end
|
|
local children = {child:GetChildren()};
|
|
for i=1,#children do
|
|
setAllChildrenParentWindow(parent, children[i]);
|
|
end
|
|
end
|
|
|
|
local function loadRegisteredWidgets(obj)
|
|
local widgets = obj.widgets;
|
|
for widget, createFun in pairs(RegisteredWidgets) do
|
|
if(widgets[widget] == nil) then
|
|
if(type(createFun) == "function") then
|
|
widgets[widget] = createFun();
|
|
widgets[widget]:SetParent(obj);
|
|
widgets[widget].widgetName = widget;
|
|
widgets[widget].parentWindow = obj;
|
|
widgets[widget].enabled = true;
|
|
widgets[widget].Enable = function(self)
|
|
self.enabled = true;
|
|
self:Show();
|
|
self.parentWindow:UpdateProps();
|
|
end
|
|
widgets[widget].Disable = function(self)
|
|
self.enabled = false;
|
|
self:Hide();
|
|
self.parentWindow:UpdateProps();
|
|
end
|
|
ApplySkinToWidget(widgets[widget]);
|
|
dPrint("Widget '"..widget.."' added to '"..obj:GetName().."'");
|
|
if(type(widgets[widget].SetDefaults) == "function") then
|
|
widgets[widget]:SetDefaults(); -- load defaults for this widget
|
|
end
|
|
end
|
|
else
|
|
if(type(widgets[widget].SetDefaults) == "function") then
|
|
widgets[widget]:SetDefaults(); -- load defaults for this widget
|
|
end
|
|
end
|
|
-- widgets[widget].parentWindow = obj;
|
|
if(type(widgets[widget]) == "table") then
|
|
widgets[widget].parentWindow = obj;
|
|
end
|
|
end
|
|
setAllChildrenParentWindow(obj, obj)
|
|
end
|
|
|
|
local function updateActiveObjects()
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse) then
|
|
loadRegisteredWidgets(WindowSoupBowl.windows[i].obj);
|
|
loadHandlers(WindowSoupBowl.windows[i].obj);
|
|
end
|
|
end
|
|
end
|
|
|
|
function scaleWindow(self, scale)
|
|
-- scale down window and preserve location
|
|
local left, top = self:SafeGetLeft()*self:GetEffectiveScale(), self:SafeGetTop()*self:GetEffectiveScale();
|
|
local setScale = self.SetScale_Orig or self.SetScale;
|
|
setScale(self, (scale > 0) and scale or 0.01)
|
|
self:ClearAllPoints();
|
|
local curScale = self:GetEffectiveScale();
|
|
curScale = (curScale > 0) and curScale or 0.01;
|
|
self:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", left/curScale, top/curScale);
|
|
end
|
|
|
|
-- create all of MessageWindow's object children
|
|
local function instantiateWindow(obj)
|
|
local fName = obj:GetName();
|
|
-- set frame's initial properties
|
|
obj:SetClampedToScreen(not WindowParent.animUp and db.clampToScreen);
|
|
obj:SetFrameStrata("DIALOG");
|
|
obj:SetMovable(true);
|
|
obj:SetToplevel(true);
|
|
obj:SetWidth(384);
|
|
obj:SetHeight(256);
|
|
obj:EnableMouse(true);
|
|
obj:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", 25, WindowParent:GetTop()-125);
|
|
obj:RegisterForDrag("LeftButton");
|
|
obj:SetScript("OnDragStart", MessageWindow_MovementControler_OnDragStart);
|
|
obj:SetScript("OnDragStop", MessageWindow_MovementControler_OnDragStop);
|
|
obj:SetScript("OnMouseUp", MessageWindow_MovementControler_OnDragStop);
|
|
obj:SetScript("OnShow", MessageWindow_Frame_OnShow);
|
|
obj:SetScript("OnHide", MessageWindow_Frame_OnHide);
|
|
obj:SetScript("OnUpdate", MessageWindow_Frame_OnUpdate);
|
|
obj.isWimWindow = true;
|
|
obj.helperFrame = helperFrame;
|
|
obj.animation = {};
|
|
|
|
obj.SetScale_Orig = obj.SetScale;
|
|
obj.SetScale = scaleWindow;
|
|
|
|
-- create animations
|
|
obj.animators = {}
|
|
obj.animators.fade = obj:CreateAnimationGroup()
|
|
obj.animators.fade.animation = obj.animators.fade:CreateAnimation("Alpha")
|
|
obj.fadeIn = function (self, force) animateFade(self, true, force) end
|
|
obj.fadeOut = function (self, force) animateFade(self, false, force) end
|
|
obj.fadedIn = true
|
|
|
|
obj.widgets = {};
|
|
local widgets = obj.widgets;
|
|
|
|
-- add window backdrop frame
|
|
widgets.Backdrop = CreateFrame("Frame", fName.."Backdrop", obj);
|
|
widgets.Backdrop:SetToplevel(false);
|
|
widgets.Backdrop:SetAllPoints(obj);
|
|
widgets.class_icon = widgets.Backdrop:CreateTexture(fName.."BackdropClassIcon", "BACKGROUND");
|
|
widgets.class_icon.widgetName = "class_icon";
|
|
widgets.class_icon.parentWindow = obj;
|
|
widgets.Backdrop.tl = widgets.Backdrop:CreateTexture(fName.."Backdrop_TL", "BORDER");
|
|
widgets.Backdrop.tr = widgets.Backdrop:CreateTexture(fName.."Backdrop_TR", "BORDER");
|
|
widgets.Backdrop.bl = widgets.Backdrop:CreateTexture(fName.."Backdrop_BL", "BORDER");
|
|
widgets.Backdrop.br = widgets.Backdrop:CreateTexture(fName.."Backdrop_BR", "BORDER");
|
|
widgets.Backdrop.t = widgets.Backdrop:CreateTexture(fName.."Backdrop_T" , "BORDER");
|
|
widgets.Backdrop.b = widgets.Backdrop:CreateTexture(fName.."Backdrop_B" , "BORDER");
|
|
widgets.Backdrop.l = widgets.Backdrop:CreateTexture(fName.."Backdrop_L" , "BORDER");
|
|
widgets.Backdrop.r = widgets.Backdrop:CreateTexture(fName.."Backdrop_R" , "BORDER");
|
|
widgets.Backdrop.bg = widgets.Backdrop:CreateTexture(fName.."Backdrop_BG", "BORDER");
|
|
widgets.from = widgets.Backdrop:CreateFontString(fName.."BackdropFrom", "OVERLAY", "GameFontNormalLarge");
|
|
widgets.from.widgetName = "from";
|
|
widgets.char_info = widgets.Backdrop:CreateFontString(fName.."BackdropCharacterDetails", "OVERLAY", "GameFontNormal");
|
|
widgets.char_info.widgetName = "char_info";
|
|
|
|
-- create core window objects
|
|
widgets.close = CreateFrame("Button", fName.."ExitButton", obj);
|
|
widgets.close:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
|
widgets.close.curTextureIndex = 1;
|
|
widgets.close.parentWindow = obj;
|
|
widgets.close.widgetName = "close";
|
|
|
|
widgets.scroll_up = CreateFrame("Button", fName.."ScrollUp", obj);
|
|
widgets.scroll_up:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
|
widgets.scroll_up.widgetName = "scroll_up";
|
|
|
|
widgets.scroll_down = CreateFrame("Button", fName.."ScrollDown", obj);
|
|
widgets.scroll_down:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
|
widgets.scroll_down.widgetName = "scroll_down";
|
|
|
|
widgets.chat_display = CreateFrame("ScrollingMessageFrame", fName.."ScrollingMessageFrame", obj);
|
|
-- widgets.chat_display:RegisterForDrag("LeftButton");
|
|
widgets.chat_display:SetHyperlinksEnabled(true)
|
|
widgets.chat_display:SetFading(false);
|
|
widgets.chat_display:SetMaxLines(128);
|
|
widgets.chat_display:SetMovable(true);
|
|
-- widgets.chat_display:SetScript("OnDragStart", function(self) MessageWindow_MovementControler_OnDragStart(self); end);
|
|
-- widgets.chat_display:SetScript("OnDragStop", function(self) MessageWindow_MovementControler_OnDragStop(self); end);
|
|
widgets.chat_display:SetJustifyH("LEFT");
|
|
widgets.chat_display:EnableMouse(true);
|
|
widgets.chat_display:EnableMouseWheel(1);
|
|
widgets.chat_display.widgetName = "chat_display";
|
|
|
|
widgets.msg_box = CreateFrame("EditBox", fName.."MsgBox", obj);
|
|
widgets.msg_box:SetAutoFocus(false);
|
|
widgets.msg_box:SetHistoryLines(32);
|
|
-- widgets.msg_box:SetMaxLetters(255);
|
|
widgets.msg_box:SetAltArrowKeyMode(true);
|
|
widgets.msg_box:EnableMouse(true);
|
|
widgets.msg_box.widgetName = "msg_box";
|
|
|
|
-- Addmessage functions
|
|
obj.AddMessage = function(self, msg, ...)
|
|
msg = applyStringModifiers(msg, self.widgets.chat_display);
|
|
self.widgets.chat_display:AddMessage(msg, ...);
|
|
updateScrollBars(self);
|
|
CallModuleFunction("OnWindowMessageAdded", self, msg, ...);
|
|
end
|
|
|
|
obj.AddMessageRaw = function(self, msg, ...)
|
|
self.widgets.chat_display:AddMessage(msg, ...);
|
|
end
|
|
|
|
obj.AddEventMessage = function(self, r, g, b, event, ...)
|
|
nextColor.r, nextColor.g, nextColor.b = r, g, b;
|
|
local str = applyMessageFormatting(self.widgets.chat_display, event, ...);
|
|
self:AddMessage(str, r, g, b);
|
|
self.msgWaiting = true;
|
|
self.lastActivity = _G.GetTime();
|
|
if(self.tabStrip) then
|
|
self.tabStrip:UpdateTabs();
|
|
end
|
|
end
|
|
|
|
obj.UpdateIcon = function(self)
|
|
local icon = self.widgets.class_icon;
|
|
if(self.type == "chat" and self.chatType) then
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.class_icon.chatAlphaMask);
|
|
local chat_type = self.chatType == "battleground" and "INSTANCE_CHAT" or string.upper(self.chatType);
|
|
local color = _G.ChatTypeInfo[chat_type]; -- Drii: ticket 344
|
|
icon:SetTexCoord(0,1,0,1);
|
|
icon:SetGradient("VERTICAL", color.r, color.g, color.b, color.r, color.g, color.b);
|
|
if(GetSelectedSkin().message_window.widgets.from.use_class_color) then
|
|
self.widgets.from:SetTextColor(color.r, color.g, color.b);
|
|
end
|
|
else
|
|
local classTag = obj.class;
|
|
icon:SetGradient("VERTICAL", 1, 1, 1, 1, 1, 1);
|
|
if(self.bn and self.bn.client == _G.BNET_CLIENT_SC2) then
|
|
classTag = "sc2";--"Interface\\FriendsFrame\\Battlenet-Sc2icon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_SC) then
|
|
classTag = "sc1";--"Interface\\FriendsFrame\\Battlenet-SCicon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_DESTINY2) then
|
|
classTag = "dsty2";--"Interface\\FriendsFrame\\Battlenet-SCicon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_COD) then
|
|
classTag = "vipr";--"Interface\\FriendsFrame\\Battlenet-SCicon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_D3) then
|
|
classTag = "d3";--"Interface\\FriendsFrame\\Battlenet-D3icon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_WTCG) then
|
|
classTag = "hs";--"Interface\\FriendsFrame\\Battlenet-WTCGicon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_HEROES) then
|
|
classTag = "hots";--"Interface\\FriendsFrame\\Battlenet-HotSicon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and self.bn.client == _G.BNET_CLIENT_OVERWATCH) then
|
|
classTag = "ow";--"Interface\\FriendsFrame\\Battlenet-Overwatchicon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.bn and (self.bn.client == _G.BNET_CLIENT_APP or self.bn.client == _G.BNET_CLIENT_CLNT or self.bn.client == "BSAp")) then--Battle.net Desktop/Mobile Apps
|
|
classTag = "bnd";--"Interface\\FriendsFrame\\Battlenet-Battleneticon"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.client_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.client_icon[classTag]));
|
|
elseif(self.class == "") then
|
|
classTag = "blank"
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.class_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.class_icon[classTag]));
|
|
else
|
|
if(constants.classes[self.class]) then
|
|
classTag = string.lower(constants.classes[self.class].tag);
|
|
classTag = string.gsub(classTag, "f$", "");
|
|
else
|
|
classTag = "blank";
|
|
end
|
|
icon:SetTexture(GetSelectedSkin().message_window.widgets.class_icon.texture);
|
|
icon:SetTexCoord(unpack(GetSelectedSkin().message_window.widgets.class_icon[classTag]));
|
|
end
|
|
if(constants.classes[self.class]) then
|
|
self.classColor = constants.classes[self.class].color;
|
|
if(GetSelectedSkin().message_window.widgets.from.use_class_color) then
|
|
self.widgets.from:SetTextColor(RGBHexToPercent(constants.classes[self.class].color));
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
obj.UpdateCharDetails = function(self)
|
|
self.widgets.char_info:SetText(GetSelectedSkin().message_window.widgets.char_info.format(self, self.guild, self.level, self.race, self.class));
|
|
end
|
|
|
|
obj.WhoCallback = function(result)
|
|
if(result and result.Online and result.Name == obj.theUser) then
|
|
obj.class = result.Class;
|
|
obj.level = result.Level;
|
|
obj.race = result.Race;
|
|
obj.guild = result.Guild;
|
|
obj.location = result.Zone;
|
|
obj:UpdateIcon();
|
|
obj:UpdateCharDetails();
|
|
end
|
|
end
|
|
|
|
obj.SendWho = function(self)
|
|
if(self.type ~= "whisper") then
|
|
return;
|
|
end
|
|
if(self.isGM) then
|
|
self.WhoCallback({
|
|
Name = self.theUser,
|
|
Online = true,
|
|
Guild = "Blizzard",
|
|
Class = L["Game Master"],
|
|
Level = "",
|
|
Race = "",
|
|
Zone = L["Unknown"]
|
|
});
|
|
elseif(self.isBN) then
|
|
-- get information of BN user from friends data.
|
|
local id = self.theUser and _G.BNet_GetBNetIDAccount(self.theUser) or nil;
|
|
if(id) then
|
|
local _, _, _, _, _, bnetIDGameAccount = GetBNGetFriendInfoByID(id)
|
|
local hasFocus, toonName, client, realmName, realmID, faction, race, class, guild, zoneName, level, gameText, broadcastText, broadcastTime = GetBNGetGameAccountInfo(bnetIDGameAccount or 0);
|
|
self.class = class or "";
|
|
self.level = level or "";
|
|
self.race = race or "";
|
|
self.guild = guild or "";
|
|
self.location = client == _G.BNET_CLIENT_WOW and zoneName or gameText;
|
|
self.bn.class = class;
|
|
self.bn.level = level;
|
|
self.bn.race = race;
|
|
self.bn.guild = guild;
|
|
self.bn.location = client == _G.BNET_CLIENT_WOW and zoneName or gameText;
|
|
self.bn.gameText = gameText;
|
|
self.bn.toonName = toonName;
|
|
self.bn.client = client;
|
|
self.bn.realmName = realmName;
|
|
self.bn.faction = faction;
|
|
self.bn.broadcastText = broadcastText;
|
|
self.bn.broadcastTime = broadcastTime;
|
|
self.bn.hasFocus = hasFocus;
|
|
self.bn.id = id;
|
|
-- self.widgets.from:SetText(self.theUser.." - "..toonName);
|
|
self:UpdateIcon();
|
|
if (client == _G.BNET_CLIENT_WOW) then
|
|
self:UpdateCharDetails();
|
|
end
|
|
else
|
|
self:AddMessage(_G.BN_UNABLE_TO_RESOLVE_NAME, db.displayColors.errorMsg.r, db.displayColors.errorMsg.g, db.displayColors.errorMsg.b);
|
|
end
|
|
else
|
|
--Check if sending unit is in your party, then check guild
|
|
if _G.IsInRaid() then
|
|
for i = 1, _G.GetNumGroupMembers() do
|
|
local unitId = "raid"..i
|
|
local name = _G.GetUnitName(unitId, true)
|
|
if self.theUser == name then
|
|
self.WhoCallback({
|
|
Name = name,
|
|
Online = true,
|
|
Guild = self.guild or "",
|
|
Class = UnitClass(unitId) or "",
|
|
Level = UnitLevel(unitId) or "",
|
|
Race = UnitRace(unitId) or "",
|
|
Zone = self.zone or ""
|
|
});
|
|
break
|
|
end
|
|
end
|
|
elseif _G.IsInGroup() then
|
|
for i = 1, _G.GetNumSubgroupMembers() do
|
|
local unitId = "party"..i
|
|
local name = _G.GetUnitName(unitId, true)
|
|
if self.theUser == name then
|
|
self.WhoCallback({
|
|
Name = name,
|
|
Online = true,
|
|
Guild = self.guild or "",
|
|
Class = UnitClass(unitId) or "",
|
|
Level = UnitLevel(unitId) or "",
|
|
Race = UnitRace(unitId) or "",
|
|
Zone = self.zone or ""
|
|
});
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if _G.IsInGuild() then
|
|
local lookupName = Ambiguate(self.theUser, "none");
|
|
local playerGuildIndex = lists.guild[lookupName];
|
|
if (playerGuildIndex) then
|
|
local name, rank, rankIndex, level, class, zone = _G.GetGuildRosterInfo(playerGuildIndex)
|
|
if name and lookupName:lower() == Ambiguate(name, "none"):lower() then --no name, means during our scan someone left guild and we hit an index that no longer returns player name, or the index is outdated and names do not match
|
|
self.WhoCallback({
|
|
Name = self.theUser,
|
|
Online = true,
|
|
Guild = select(1, GetGuildInfo("player")) or "",
|
|
Class = class or "",
|
|
Level = level or "",
|
|
Race = self.race or "",
|
|
Zone = zone or ""
|
|
});
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
obj.GetRuleSet = function(self)
|
|
if(db.pop_rules[self.type]) then
|
|
local curState = db.pop_rules[self.type].alwaysOther and "other" or curState
|
|
return db.pop_rules[self.type][curState];
|
|
else
|
|
return db.pop_rules.whisper.other;
|
|
end
|
|
end
|
|
|
|
-- PopUp rules
|
|
obj.Pop = function(self, msgDirection, forceResult, forceFocus) -- true to force show, false it ignore rules and force quiet.
|
|
-- account for variable arguments.
|
|
if(type(msgDirection) == "boolean") then
|
|
forceResult, forceFocus = msgDirection, forceResult;
|
|
msgDirection = "in";
|
|
elseif(msgDirection == nil) then
|
|
msgDirection = "in";
|
|
end
|
|
|
|
local rules = self:GetRuleSet(); -- defaults incase unknown
|
|
|
|
-- pass isNew to pop ruleset.
|
|
if(forceResult == true) then
|
|
-- go by forceResult and ignore rules
|
|
if(self.tabStrip) then
|
|
-- if(not EditBoxInFocus) then
|
|
ShowContainer();
|
|
self.tabStrip:JumpToTab(self);
|
|
if(not getVisibleChatFrameEditBox() and (rules.autofocus or forceFocus)) then
|
|
self.widgets.msg_box:SetFocus();
|
|
end
|
|
-- end
|
|
else
|
|
ShowContainer();
|
|
self:ResetAnimation();
|
|
self:Show();
|
|
if((not getVisibleChatFrameEditBox() and not EditBoxInFocus and rules.autofocus) or forceFocus) then
|
|
self.widgets.msg_box:SetFocus();
|
|
end
|
|
local count = 0;
|
|
for i=1, #WindowSoupBowl.windows do
|
|
count = WindowSoupBowl.windows[i].obj:IsShown() and count + 1 or count;
|
|
end
|
|
--[[ if(count > 1) then
|
|
DisplayTutorial(L["Creating Tab Groups"], L["You can group two or many windows together by <Shift-Clicking> a window and dragging it on top of another."]);
|
|
else
|
|
DisplayTutorial(L["Resizing Windows"], L["You can resize a window by holding <Shift> and dragging the bottom right corner of the window."]);
|
|
end-- ]]
|
|
end
|
|
else
|
|
-- execute pop rules.
|
|
if((rules.onSend and msgDirection == "out") or (rules.onReceive and msgDirection == "in")) then
|
|
if(self.tabStrip) then
|
|
self:ResetAnimation();
|
|
local infocus = EditBoxInFocus and EditBoxInFocus:GetParent().tabStrip;
|
|
if(infocus ~= self.tabStrip) then
|
|
self.tabStrip:JumpToTab(self);
|
|
setWindowAsFadedIn(self);
|
|
end
|
|
else
|
|
self:ResetAnimation();
|
|
self:Show();
|
|
setWindowAsFadedIn(self);
|
|
end
|
|
if(self:IsVisible() and not getVisibleChatFrameEditBox and not EditBoxInFocus and rules.autofocus) then
|
|
self.widgets.msg_box:SetFocus();
|
|
end
|
|
end
|
|
end
|
|
|
|
-- at this state the message is no longer classified as a new window, reset flag.
|
|
obj.isNew = false;
|
|
CallModuleFunction("OnWindowPopped", self);
|
|
end
|
|
|
|
obj.UpdateProps = function(self)
|
|
self:SetFrameStrata(db.winSize.strata);
|
|
self:SetScale(db.winSize.scale/100);
|
|
self.widgets.Backdrop:SetAlpha(db.windowAlpha/100);
|
|
local Path,_,Flags = self.widgets.chat_display:GetFont();
|
|
self:SetClampedToScreen(not WindowParent.animUp and db.clampToScreen);
|
|
self.widgets.chat_display:SetFont(Path or _G["ChatFontNormal"]:GetFont(),db.fontSize+2,Flags);
|
|
self.widgets.chat_display:SetAlpha(1);
|
|
self.widgets.chat_display:SetIndentedWordWrap(db.wordwrap_indent);
|
|
self.widgets.msg_box:SetAlpha(1);
|
|
self.widgets.msg_box:SetAltArrowKeyMode(db.ignoreArrowKeys);
|
|
|
|
self.widgets.from:SetAlpha(1);
|
|
self.widgets.char_info:SetAlpha(1);
|
|
self.widgets.close:SetAlpha(db.windowAlpha);
|
|
self.widgets.scroll_up:SetAlpha(db.windowAlpha);
|
|
self.widgets.scroll_down:SetAlpha(db.windowAlpha);
|
|
|
|
if(not self.customSize) then
|
|
self:SetWidth(db.winSize.width);
|
|
self:SetHeight(db.winSize.height);
|
|
end
|
|
|
|
local minWidth, minHeight = GetSelectedSkin().message_window.min_width, GetSelectedSkin().message_window.min_height;
|
|
|
|
-- process registered widgets
|
|
local widgetName, widgetObj;
|
|
for widgetName, widgetObj in pairs(obj.widgets) do
|
|
if(type(widgetObj.UpdateProps) == "function") then
|
|
widgetObj:UpdateProps();
|
|
end
|
|
if(widgetObj.type) then
|
|
if(widgetObj.enabled and string.match(widgetObj.type, obj.type)) then
|
|
widgetObj:Show();
|
|
local w, h = widgetObj:GetWidth(), widgetObj:GetHeight();
|
|
minWidth = _G.math.max(minWidth, (self:SafeGetLeft() - widgetObj:GetLeft()) + w + (widgetObj:GetRight() - self:SafeGetRight()));
|
|
minHeight = _G.math.max(minHeight, (self:SafeGetTop() - widgetObj:GetTop() - WindowParent:GetBottom()) + h + (widgetObj:GetBottom() - self:SafeGetBottom() - WindowParent:GetBottom()));
|
|
else
|
|
widgetObj:Hide()
|
|
end
|
|
end
|
|
end
|
|
self:SetMinResize(minWidth, minHeight);
|
|
self:SetWidth(_G.math.max(minWidth, self:GetWidth()));
|
|
self:SetHeight(_G.math.max(minHeight, self:GetHeight()));
|
|
self.initialized = true;
|
|
end
|
|
|
|
obj.Hide_Normal = obj.Hide;
|
|
obj.Hide = function(self, animate)
|
|
if(not self:IsShown() or self.animation.mode) then
|
|
-- don't do anything if window is already hidden.
|
|
return;
|
|
end
|
|
if(not animate) then
|
|
self:Hide_Normal();
|
|
self:ResetAnimation();
|
|
else
|
|
|
|
if(not db.winAnimation) then
|
|
self:Hide_Normal();
|
|
self:ResetAnimation();
|
|
else
|
|
self.widgets.chat_display:SetParent("UIParent");
|
|
self.widgets.chat_display:Hide();
|
|
local a = self.animation;
|
|
obj:SetClampedToScreen(false);
|
|
a.initLeft = self:SafeGetLeft();
|
|
a.initTop = self:SafeGetTop();
|
|
a.to = MinimapIcon or nil;
|
|
a.elapsed, a.time = 0, .5;
|
|
a.scaleLimit = .001 -- _G.math.max(_G.math.ceil((100-_G.UIParent:GetScale()*100)/2)/100 + .04, .01);
|
|
a.mode = "HIDE"; -- this starts the animation
|
|
dPrint("Animation Started: "..self:GetName());
|
|
end
|
|
end
|
|
end
|
|
obj.ResetAnimation = function(self)
|
|
if(self.animation.mode) then
|
|
self:SetClampedToScreen(not WindowParent.animUp and db.clampToScreen);
|
|
self:SetScale_Orig(db.winSize.scale/100);
|
|
self:ClearAllPoints();
|
|
self:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", self.animation.initLeft, self.animation.initTop - WindowParent:GetBottom());
|
|
self.widgets.chat_display:Show();
|
|
self.widgets.chat_display:SetParent(self);
|
|
dPrint("Animation Reset: "..self:GetName());
|
|
end
|
|
for key, _ in pairs(self.animation) do
|
|
self.animation[key] = nil;
|
|
end
|
|
end
|
|
obj.SafeGetLeft = function(self)
|
|
return self:GetLeft() - WindowParent:GetLeft();
|
|
end
|
|
obj.SafeGetRight = function(self)
|
|
return self:GetRight() - WindowParent:GetLeft();
|
|
end
|
|
obj.SafeGetTop = function(self)
|
|
return self:GetTop() - WindowParent:GetBottom();
|
|
end
|
|
obj.SafeGetBottom = function(self)
|
|
return self:GetBottom() - WindowParent:GetBottom();
|
|
end
|
|
|
|
-- enforce that all core widgets have parentWindow set.
|
|
local w;
|
|
for _, w in pairs(obj.widgets) do
|
|
w.parentWindow = obj;
|
|
end
|
|
|
|
-- load Registered Widgets
|
|
loadRegisteredWidgets(obj);
|
|
loadHandlers(obj);
|
|
|
|
-- local shortcuts = CreateFrame("Frame", fName.."ShortcutFrame", obj);
|
|
-- shortcuts:SetToplevel(true);
|
|
-- shortcuts:SetFrameStrata("DIALOG");
|
|
-- for i=1,ShortcutCount do
|
|
-- CreateFrame("Button", fName.."ShortcutFrameButton"..i, shortcuts, "WIM_ShortcutButtonTemplate");
|
|
-- end
|
|
|
|
end
|
|
|
|
local function placeWindow(win)
|
|
win:ClearAllPoints();
|
|
local lastWindow = nil;
|
|
for i=1, #windowsByAge do
|
|
if(windowsByAge[i] ~= win and windowsByAge[i]:IsShown() and windowsByAge[i].hasMoved == false) then
|
|
lastWindow = windowsByAge[i];
|
|
break;
|
|
end
|
|
end
|
|
if (not lastWindow or db.winCascade.enabled == false) or (db.tabs.whispers.enabled and win.type == "whisper") or (db.tabs.chat.enabled and win.type == "chat") then
|
|
win:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", db.winLoc.left/win:GetEffectiveScale(), (db.winLoc.top)/win:GetEffectiveScale());
|
|
else
|
|
local casc = cascadeDirection[db.winCascade.direction];
|
|
win:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", lastWindow:SafeGetLeft()+casc[1], lastWindow:SafeGetTop()+casc[2]);
|
|
end
|
|
end
|
|
|
|
|
|
-- load object into it's default state.
|
|
local function loadWindowDefaults(obj)
|
|
obj:Hide();
|
|
obj.age = _G.GetTime();
|
|
obj.hasMoved = false;
|
|
|
|
obj.lastActivity = _G.GetTime();
|
|
|
|
obj.customSize = false;
|
|
|
|
obj.guild = "";
|
|
obj.level = "";
|
|
obj.race = "";
|
|
obj.class = "";
|
|
obj.location = "";
|
|
obj.demoSave = nil;
|
|
obj.classColor = "ffffff";
|
|
|
|
obj.isGM = lists.gm[obj.theUser];
|
|
|
|
obj:UpdateIcon();
|
|
obj.isNew = true;
|
|
|
|
obj:SetScale(1);
|
|
obj:SetAlpha(1);
|
|
|
|
obj.widgets.Backdrop:SetAlpha(1);
|
|
|
|
obj.widgets.from:SetText(GetReadableName(obj.theUser));
|
|
obj.widgets.from:SetTextColor(RGBHexToPercent(GetSelectedSkin().message_window.widgets.from.font_color));
|
|
|
|
obj.widgets.char_info:SetText("");
|
|
|
|
obj.widgets.msg_box.setText = 0;
|
|
obj.widgets.msg_box:SetText("");
|
|
obj.widgets.msg_box:Show();
|
|
|
|
obj.widgets.chat_display:Clear();
|
|
obj.widgets.chat_display:AddMessage(" ");
|
|
obj.widgets.chat_display:AddMessage(" ");
|
|
updateScrollBars(obj);
|
|
|
|
obj.widgets.close.forceShift = false;
|
|
|
|
-- load Registered Widgets (if not created already) & set defaults
|
|
loadRegisteredWidgets(obj);
|
|
loadHandlers(obj);
|
|
|
|
-- process registered widgets
|
|
local widgetName, widgetObj;
|
|
for widgetName, widgetObj in pairs(obj.widgets) do
|
|
if(type(widgetObj.SetDefaults) == "function") then
|
|
widgetObj:SetDefaults();
|
|
end
|
|
end
|
|
ApplySkinToWindow(obj);
|
|
obj:UpdateProps();
|
|
placeWindow(obj);
|
|
end
|
|
|
|
-- Create (recycle if available) message window. Returns object.
|
|
-- (wtype == "whisper", "chat" or "w2w")
|
|
local function createWindow(userName, wtype)
|
|
if(type(userName) ~= "string") then
|
|
return;
|
|
end
|
|
-- if(type(WIM:GetSelectedSkin()) ~= "table") then
|
|
-- WIM:LoadSkin(WIM.db.skin.selected, WIM.db.skin.style);
|
|
-- end
|
|
local func = function ()
|
|
if(WindowSoupBowl.available > 0) then
|
|
local i;
|
|
for i=1,#WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse == false) then
|
|
return WindowSoupBowl.windows[i].obj, i;
|
|
end
|
|
end
|
|
else
|
|
return nil;
|
|
end
|
|
end
|
|
local obj, index = func();
|
|
if(obj) then
|
|
-- object available...
|
|
WindowSoupBowl.available = WindowSoupBowl.available - 1;
|
|
WindowSoupBowl.used = WindowSoupBowl.used + 1;
|
|
WindowSoupBowl.windows[index].inUse = true;
|
|
WindowSoupBowl.windows[index].user = userName;
|
|
obj.theUser = userName;
|
|
obj.type = wtype;
|
|
loadWindowDefaults(obj); -- clear contents of window and revert back to it's initial state.
|
|
dPrint("Window recycled '"..obj:GetName().."'");
|
|
CallModuleFunction("OnWindowCreated", obj);
|
|
table.insert(windowsByAge, obj);
|
|
table.sort(windowsByAge, function(a, b) return a.age > b.age; end);
|
|
return obj;
|
|
else
|
|
-- must create new object
|
|
WindowSoupBowl.used = WindowSoupBowl.used + 1;
|
|
WindowSoupBowl.windowToken = WindowSoupBowl.windowToken + 1; -- increment token for propper frame name creation.
|
|
local fName = "WIM3_msgFrame"..WindowSoupBowl.windowToken;
|
|
local f = CreateFrame("Frame",fName, WindowParent);
|
|
local winTable = {
|
|
user = userName,
|
|
frameName = fName,
|
|
inUse = true,
|
|
obj = f
|
|
};
|
|
table.insert(WindowSoupBowl.windows, winTable);
|
|
f.theUser = userName;
|
|
f.type = wtype;
|
|
f.isParent = true;
|
|
instantiateWindow(f);
|
|
-- f.icon.theUser = userName;
|
|
loadWindowDefaults(f);
|
|
dPrint("Window created '"..f:GetName().."'");
|
|
CallModuleFunction("OnWindowCreated", f);
|
|
table.insert(windowsByAge, f);
|
|
table.sort(windowsByAge, function(a, b) return a.age > b.age; end);
|
|
return f;
|
|
end
|
|
end
|
|
|
|
|
|
-- Returns object, SoupBowl_windows_index or nil if window can not be found.
|
|
local function getWindowByName(userName)
|
|
if(type(userName) ~= "string") then
|
|
return nil;
|
|
end
|
|
for i=1,#WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].user == userName) then
|
|
return WindowSoupBowl.windows[i].obj, i;
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Deletes message window and makes it available in the Soup Bowl.
|
|
local function destroyWindow(userNameOrObj)
|
|
local obj, index;
|
|
if(type(userNameOrObj) == "string") then
|
|
obj, index = getWindowByName(userNameOrObj);
|
|
else
|
|
obj, index = getWindowByName(userNameOrObj.theUser);
|
|
end
|
|
|
|
if(obj) then
|
|
if(obj.tabStrip) then
|
|
obj.tabStrip:Detach(obj);
|
|
end
|
|
WindowSoupBowl.windows[index].inUse = false;
|
|
WindowSoupBowl.windows[index].user = "";
|
|
WindowSoupBowl.available = WindowSoupBowl.available + 1;
|
|
WindowSoupBowl.used = WindowSoupBowl.used - 1;
|
|
|
|
obj:Show();
|
|
obj.widgets.chat_display:Clear();
|
|
obj:Hide();
|
|
obj.initialized = nil;
|
|
dPrint("Window '"..obj:GetName().."' destroyed.");
|
|
CallModuleFunction("OnWindowDestroyed", obj);
|
|
removeFromTable(windowsByAge, obj);
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function RegisterWidgetTrigger(WidgetName, wType, HandlerName, Function)
|
|
-- config table to handle widget
|
|
if(not Widget_Triggers[WidgetName]) then
|
|
Widget_Triggers[WidgetName] = {}
|
|
end
|
|
-- config widget table to handle hander
|
|
if(not Widget_Triggers[WidgetName][HandlerName]) then
|
|
Widget_Triggers[WidgetName][HandlerName] = {
|
|
whisper = {},
|
|
chat = {},
|
|
w2w = {},
|
|
demo = {},
|
|
};
|
|
end
|
|
-- register to table
|
|
for i=1,select("#", string.split(",", wType)) do
|
|
table.insert(Widget_Triggers[WidgetName][HandlerName][select(i, string.split(",", wType))], Function);
|
|
end
|
|
updateActiveObjects();
|
|
end
|
|
|
|
function GetWindowSoupBowl()
|
|
return WindowSoupBowl;
|
|
end
|
|
|
|
function CreateWhisperWindow(playerName)
|
|
return createWindow(playerName, "whisper");
|
|
end
|
|
|
|
function CreateChatWindow(chatName)
|
|
return createWindow(chatName, "chat");
|
|
end
|
|
|
|
function CreateW2WWindow(chatName)
|
|
return createWindow(chatName, "w2w");
|
|
end
|
|
|
|
function DestroyWindow(playerNameOrObject)
|
|
destroyWindow(playerNameOrObject);
|
|
end
|
|
|
|
function ShowDemoWindow()
|
|
if(options.frame and options.frame:IsShown()) then
|
|
options.frame:Disable();
|
|
if(not WIM.DemoWindow) then
|
|
WIM.DemoWindow = createWindow(L["Demo Window"], "demo");
|
|
end
|
|
WIM.DemoWindow:Show();
|
|
WIM.DemoWindow.demoSave = true;
|
|
end
|
|
end
|
|
|
|
|
|
function RegisterWidget(widgetName, createFunction, moduleName)
|
|
-- moduleName is optional if not being called from a module.
|
|
-- including module name will force the UI to be reloaded before removing the widgets.
|
|
RegisteredWidgets[widgetName] = createFunction;
|
|
if(moduleName) then
|
|
modules[moduleName].hasWidget = true;
|
|
end
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse) then
|
|
loadRegisteredWidgets(WindowSoupBowl.windows[i].obj);
|
|
end
|
|
end
|
|
updateActiveObjects();
|
|
end
|
|
|
|
-- iterator: All loaded widgets
|
|
function Widgets(widgetName)
|
|
local index = 1
|
|
return function()
|
|
for i=index, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].obj.widgets[widgetName]) then
|
|
index = i+1;
|
|
return WindowSoupBowl.windows[i].obj.widgets[widgetName];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function RegisterStringModifier(fun, prioritize)
|
|
addToTableUnique(StringModifiers, fun, prioritize);
|
|
end
|
|
|
|
function UnregisterStringModifier(fun)
|
|
removeFromTable(StringModifiers, fun);
|
|
end
|
|
|
|
function RegisterMessageFormatting(name, fun)
|
|
table.insert(FormattingCalls, {
|
|
name = name,
|
|
fun = fun
|
|
});
|
|
table.insert(FormattingCallsList, name);
|
|
end
|
|
|
|
function GetMessageFormattingList()
|
|
return FormattingCallsList;
|
|
end
|
|
|
|
function HideAllWindows(type)
|
|
ShowContainer();
|
|
type = type and string.lower(type) or nil;
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse and WindowSoupBowl.windows[i].obj.type == (type or WindowSoupBowl.windows[i].obj.type)) then
|
|
WindowSoupBowl.windows[i].obj:Hide(true);
|
|
end
|
|
end
|
|
end
|
|
|
|
local showAllTbl = {};
|
|
function ShowAllWindows(type)
|
|
type = type and string.lower(type) or nil;
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse and WindowSoupBowl.windows[i].obj.type == (type or WindowSoupBowl.windows[i].obj.type)) then
|
|
local obj = WindowSoupBowl.windows[i] and WindowSoupBowl.windows[i].obj;
|
|
if(obj.tabStrip and #obj.tabStrip.attached > 1) then
|
|
if(addToTableUnique(showAllTbl, obj.tabStrip)) then
|
|
obj.tabStrip.selected.obj:Pop(true);
|
|
end
|
|
else
|
|
WindowSoupBowl.windows[i].obj:Pop(true);
|
|
end
|
|
end
|
|
end
|
|
-- clean table
|
|
for key, _ in pairs(showAllTbl) do
|
|
showAllTbl[key] = nil;
|
|
end
|
|
end
|
|
|
|
local showAllUnreadTbl = {};
|
|
function ShowAllUnreadWindows(type)
|
|
type = type and string.lower(type) or nil;
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse and WindowSoupBowl.windows[i].obj.type == (type or WindowSoupBowl.windows[i].obj.type)) then
|
|
local obj = WindowSoupBowl.windows[i] and WindowSoupBowl.windows[i].obj;
|
|
if(obj and obj.unreadCount and obj.unreadCount > 0) then
|
|
if(obj.tabStrip) then
|
|
if(addToTableUnique(showAllUnreadTbl, obj.tabStrip)) then
|
|
WindowSoupBowl.windows[i].obj:Pop(true);
|
|
end
|
|
else
|
|
WindowSoupBowl.windows[i].obj:Pop(true);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- clean table
|
|
for key, _ in pairs(showAllUnreadTbl) do
|
|
showAllUnreadTbl[key] = nil;
|
|
end
|
|
end
|
|
|
|
|
|
function UpdateAllWindowProps()
|
|
for i=1, #WindowSoupBowl.windows do
|
|
if(WindowSoupBowl.windows[i].inUse) then
|
|
WindowSoupBowl.windows[i].obj:UpdateProps();
|
|
end
|
|
end
|
|
end
|
|
|
|
function AddEscapeWindow(frame)
|
|
for i=1, #_G.UISpecialFrames do
|
|
if(_G.UISpecialFrames[i] == frame:GetName()) then
|
|
return;
|
|
end
|
|
end
|
|
table.insert(_G.UISpecialFrames, frame:GetName());
|
|
end
|
|
|
|
function RemoveEscapeWindow(frame)
|
|
for i=1, #_G.UISpecialFrames do
|
|
if(_G.UISpecialFrames[i] == frame:GetName()) then
|
|
table.remove(_G.UISpecialFrames, i);
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
------------------------------------
|
|
-- WindowParent - Container Calls --
|
|
------------------------------------
|
|
|
|
|
|
local function WindowParent_AnimPos(self, fraction)
|
|
if(db.expose.direction == 1) then
|
|
-- UP
|
|
return "BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", 0, fraction*(_G.UIParent:GetHeight());
|
|
elseif(db.expose.direction == 2) then
|
|
-- DOWN
|
|
return "BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", 0, -fraction*(_G.UIParent:GetHeight());
|
|
elseif(db.expose.direction == 3) then
|
|
-- LEFT
|
|
return "BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", -fraction*(_G.UIParent:GetWidth()), 0;
|
|
elseif(db.expose.direction == 4) then
|
|
-- RIGHT
|
|
return "BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", fraction*(_G.UIParent:GetWidth()), 0;
|
|
end
|
|
end
|
|
|
|
local WindowParentAnimTable = {
|
|
totalTime = 0.5,
|
|
updateFunc = "SetPoint",
|
|
getPosFunc = WindowParent_AnimPos,
|
|
}
|
|
|
|
local function WindowParent_AnimFinished(self)
|
|
self.animFinished = true;
|
|
if(self.animUp) then
|
|
self:Hide();
|
|
else
|
|
self:SetPoint("BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", 0, 0);
|
|
self:SetWidth(_G.UIParent:GetWidth());
|
|
self:SetHeight(_G.UIParent:GetHeight());
|
|
end
|
|
for i=1, #WindowSoupBowl.windows do
|
|
local win = WindowSoupBowl.windows[i].obj;
|
|
win:SetClampedToScreen(not self.animUp and db.clampToScreen);
|
|
if(win:IsVisible()) then
|
|
WIM.CallModuleFunction("OnWindowShow", win);
|
|
end
|
|
end
|
|
end
|
|
|
|
function ShowContainer(animate)
|
|
if(not WindowParent.animUp) then
|
|
return;
|
|
end
|
|
WindowParent:Show();
|
|
WindowParent.animUp = false;
|
|
if(animate) then
|
|
WindowParentAnimTable.totalTime = 0.3;
|
|
else
|
|
WindowParentAnimTable.totalTime = 0;
|
|
end
|
|
WindowParent.animFinished = false;
|
|
WindowParent.inSequence = true;
|
|
--[[for i=1, #WindowSoupBowl.windows do
|
|
local win = WindowSoupBowl.windows[i].obj;
|
|
win:SetClampedToScreen(false);
|
|
local left, top = win:SafeGetLeft(), win:SafeGetTop()*win:GetScale();
|
|
win:ClearAllPoints();
|
|
win:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", left, top);
|
|
win:SetClampedToScreen(false);
|
|
end]]
|
|
if(animate) then
|
|
WIM.SetUpAnimation(WindowParent, WindowParentAnimTable, WindowParent_AnimFinished, true);
|
|
else
|
|
WindowParent:SetPoint(WindowParent_AnimPos(WindowParent, 100));
|
|
WindowParent_AnimFinished(WindowParent);
|
|
end
|
|
WIM.CallModuleFunction("OnContainerShow");
|
|
end
|
|
|
|
function HideContainer(animate)
|
|
if(WindowParent.animUp) then
|
|
return;
|
|
end
|
|
WindowParent.animUp = true;
|
|
if(animate) then
|
|
WindowParentAnimTable.totalTime = 0.3;
|
|
else
|
|
WindowParentAnimTable.totalTime = 0;
|
|
end
|
|
WindowParent.animFinished = false;
|
|
WindowParent.inSequence = true;
|
|
for i=1, #WindowSoupBowl.windows do
|
|
local win = WindowSoupBowl.windows[i].obj;
|
|
win:SetClampedToScreen(false);
|
|
local left, top = win:SafeGetLeft(), win:SafeGetTop();
|
|
win:ClearAllPoints();
|
|
win:SetPoint("TOPLEFT", WindowParent, "BOTTOMLEFT", left, top);
|
|
win:SetClampedToScreen(false);
|
|
end
|
|
if(animate) then
|
|
WIM.SetUpAnimation(WindowParent, WindowParentAnimTable, WindowParent_AnimFinished, false);
|
|
else
|
|
WindowParent:SetPoint(WindowParent_AnimPos(WindowParent, 0));
|
|
WindowParent_AnimFinished(WindowParent);
|
|
end
|
|
WIM.CallModuleFunction("OnContainerHide");
|
|
end
|
|
|
|
function ToggleContainer(animate)
|
|
if(WindowParent.animUp) then
|
|
ShowContainer(animate);
|
|
else
|
|
HideContainer(animate);
|
|
end
|
|
end
|
|
|
|
|
|
----------------------------------
|
|
-- Set default widget triggers --
|
|
----------------------------------
|
|
|
|
RegisterWidgetTrigger("close", "whisper,chat,w2w", "OnEnter", function(self)
|
|
if(db.showToolTips == true) then
|
|
_G.GameTooltip:SetOwner(self, "ANCHOR_TOPRIGHT");
|
|
_G.GameTooltip:SetText(L["<Shift-Click> to close window."]);
|
|
end
|
|
end);
|
|
|
|
RegisterWidgetTrigger("close", "whisper,chat,w2w", "OnLeave", function(self) _G.GameTooltip:Hide(); end);
|
|
|
|
RegisterWidgetTrigger("close", "whisper,chat,w2w,demo", "OnClick", function(self)
|
|
if(IsShiftKeyDown() or self.forceShift or self.parentWindow.type == "demo") then
|
|
self.forceShift = false;
|
|
destroyWindow(self:GetParent());
|
|
else
|
|
-- DisplayTutorial(L["Message Window Hidden"], L["WIM's message window has been hidden to WIM's Minimap Icon. If you want to end a conversation, you may do so by <Shift-Clicking> the close button."]);
|
|
self:GetParent():Hide(true);
|
|
end
|
|
end);
|
|
|
|
RegisterWidgetTrigger("close", "whisper,chat,w2w", "OnUpdate", function(self)
|
|
local SelectedSkin = WIM:GetSelectedSkin();
|
|
if(GetMouseFocus() == self) then
|
|
if(IsShiftKeyDown() and self.curTextureIndex == 1) then
|
|
self:SetNormalTexture(SelectedSkin.message_window.widgets.close.state_close.NormalTexture);
|
|
self:SetPushedTexture(SelectedSkin.message_window.widgets.close.state_close.PushedTexture);
|
|
self:SetHighlightTexture(SelectedSkin.message_window.widgets.close.state_close.HighlightTexture, SelectedSkin.message_window.widgets.close.state_close.HighlightAlphaMode);
|
|
self.curTextureIndex = 2;
|
|
elseif(not IsShiftKeyDown() and self.curTextureIndex == 2) then
|
|
self:SetNormalTexture(SelectedSkin.message_window.widgets.close.state_hide.NormalTexture);
|
|
self:SetPushedTexture(SelectedSkin.message_window.widgets.close.state_hide.PushedTexture);
|
|
self:SetHighlightTexture(SelectedSkin.message_window.widgets.close.state_hide.HighlightTexture, SelectedSkin.message_window.widgets.close.state_hide.HighlightAlphaMode);
|
|
self.curTextureIndex = 1;
|
|
end
|
|
elseif(self.curTextureIndex == 2) then
|
|
self:SetNormalTexture(SelectedSkin.message_window.widgets.close.state_hide.NormalTexture);
|
|
self:SetPushedTexture(SelectedSkin.message_window.widgets.close.state_hide.PushedTexture);
|
|
self:SetHighlightTexture(SelectedSkin.message_window.widgets.close.state_hide.HighlightTexture, SelectedSkin.message_window.widgets.close.state_hide.HighlightAlphaMode);
|
|
self.curTextureIndex = 1;
|
|
end
|
|
end);
|
|
|
|
RegisterWidgetTrigger("scroll_up", "whisper,chat,w2w", "OnClick", function(self)
|
|
local obj = self:GetParent();
|
|
if( _G.IsControlKeyDown() ) then
|
|
obj.widgets.chat_display:ScrollToTop();
|
|
else
|
|
if( _G.IsShiftKeyDown() ) then
|
|
obj.widgets.chat_display:PageUp();
|
|
else
|
|
obj.widgets.chat_display:ScrollUp();
|
|
end
|
|
end
|
|
updateScrollBars(obj);
|
|
end);
|
|
|
|
RegisterWidgetTrigger("scroll_down", "whisper,chat,w2w", "OnClick", function(self)
|
|
local obj = self:GetParent();
|
|
if( _G.IsControlKeyDown() ) then
|
|
obj.widgets.chat_display:ScrollToBottom();
|
|
else
|
|
if( _G.IsShiftKeyDown() ) then
|
|
obj.widgets.chat_display:PageDown();
|
|
else
|
|
obj.widgets.chat_display:ScrollDown();
|
|
end
|
|
end
|
|
updateScrollBars(obj);
|
|
end);
|
|
|
|
RegisterWidgetTrigger("chat_display", "whisper,chat,w2w", "OnMouseWheel", function(self, ...)
|
|
if(select(1, ...) > 0) then
|
|
if( _G.IsControlKeyDown() ) then
|
|
self:ScrollToTop();
|
|
else
|
|
if( _G.IsShiftKeyDown() ) then
|
|
self:PageUp();
|
|
else
|
|
self:ScrollUp();
|
|
end
|
|
end
|
|
else
|
|
if( _G.IsControlKeyDown() ) then
|
|
self:ScrollToBottom();
|
|
else
|
|
if( _G.IsShiftKeyDown() ) then
|
|
self:PageDown();
|
|
else
|
|
self:ScrollDown();
|
|
end
|
|
end
|
|
end
|
|
updateScrollBars(getParentMessageWindow(self));
|
|
end);
|
|
|
|
RegisterWidgetTrigger("chat_display", "whisper,chat,w2w,demo", "OnMouseDown", function(self)
|
|
self:GetParent().prevLeft = self:GetParent():SafeGetLeft();
|
|
self:GetParent().prevTop = self:GetParent():SafeGetTop();
|
|
MessageWindow_MovementControler_OnDragStart(self);
|
|
end);
|
|
|
|
RegisterWidgetTrigger("chat_display", "whisper,chat,w2w,demo", "OnMouseUp", function(self)
|
|
MessageWindow_MovementControler_OnDragStop(self);
|
|
if(self.parentWindow ~= DemoWindow) then
|
|
self:Hide();
|
|
self:Show();
|
|
end
|
|
if(self:GetParent().prevLeft == self:GetParent():SafeGetLeft() and self:GetParent().prevTop == self:GetParent():SafeGetTop() and self.parentWindow ~= DemoWindow) then
|
|
--[ Frame was clicked not dragged
|
|
local msg_box = self:GetParent().widgets.msg_box;
|
|
if(EditBoxInFocus == nil) then
|
|
msg_box:SetFocus();
|
|
else
|
|
if(EditBoxInFocus == msg_box) then
|
|
msg_box:Hide();
|
|
msg_box:Show();
|
|
else
|
|
msg_box:SetFocus();
|
|
end
|
|
end
|
|
end
|
|
end);
|
|
|
|
local myself = _G.UnitName("player")
|
|
RegisterWidgetTrigger("chat_display", "whisper,chat,w2w", "OnHyperlinkClick", function(self, link, text, button)
|
|
local t,n,i = string.split(":", link)
|
|
if n == myself then
|
|
return
|
|
end
|
|
if link == "garrmission:weakauras" then
|
|
_G.SetItemRef(link, text, button, self);
|
|
else
|
|
_G.SetItemRef(link, text:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""), button, self);
|
|
end
|
|
end);
|
|
--RegisterWidgetTrigger("chat_display", "whisper,chat,w2w","OnMessageScrollChanged", function(self) updateScrollBars(self:GetParent()); end);
|
|
|
|
local lastTTlink
|
|
RegisterWidgetTrigger("chat_display", "whisper,chat,w2w", "OnHyperlinkEnter", function(self, link)
|
|
local obj = self.parentWindow;
|
|
obj.isOnHyperLink = true;
|
|
if(db.hoverLinks) then
|
|
local t = string.match(link, "^(.-):")
|
|
if(t == "item" or t == "enchant" or t == "spell" or t == "quest") then
|
|
lastTTlink = t
|
|
_G.GameTooltip:SetOwner(_G.UIParent, "ANCHOR_CURSOR");
|
|
_G.GameTooltip:SetHyperlink(link);
|
|
_G.GameTooltip:Show();
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterWidgetTrigger("chat_display", "whisper,chat,w2w", "OnHyperlinkLeave", function(self, link)
|
|
local obj = self.parentWindow;
|
|
obj.isOnHyperLink = false;
|
|
if(db.hoverLinks) then
|
|
local t = lastTTlink --string.match(link, "^(.-):")
|
|
if(t == "item" or t == "enchant" or t == "spell" or t == "quest") then
|
|
_G.GameTooltip:ClearLines()
|
|
_G.GameTooltip:Hide()
|
|
lastTTlink = nil
|
|
end
|
|
end
|
|
end)
|
|
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w,demo", "OnEnterPressed", function(self)
|
|
if(strsub(self:GetText(), 1, 1) == "/") then
|
|
EditBoxInFocus = nil;
|
|
_G.ChatFrame1EditBox:SetText(self:GetText());
|
|
_G.ChatEdit_SendText(_G.ChatFrame1EditBox, 1);
|
|
self:SetText("");
|
|
EditBoxInFocus = self;
|
|
else
|
|
if(self:GetText() == "") then
|
|
self:Hide();
|
|
self:Show();
|
|
return;
|
|
end
|
|
end
|
|
-- keep focus or not
|
|
if(self:GetParent():GetRuleSet().keepfocus) then
|
|
self:SetFocus();
|
|
else
|
|
self:Hide();
|
|
self:Show();
|
|
end
|
|
|
|
end);
|
|
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w,demo", "OnEscapePressed", function(self)
|
|
self:SetText("");
|
|
self:Hide();
|
|
self:Show();
|
|
end);
|
|
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w,demo", "OnUpdate", function(self)
|
|
if(self.setText == 1) then
|
|
self.setText = 0;
|
|
self:SetText(self.textToSet or "");
|
|
self.textToSet = "";
|
|
end
|
|
end);
|
|
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnEditFocusGained", function(self)
|
|
EditBoxInFocus = self;
|
|
-- _G.ACTIVE_CHAT_EDIT_BOX = self; -- preserve linking abilities.
|
|
end);
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnEditFocusLost", function(self)
|
|
EditBoxInFocus = nil;
|
|
-- _G.ACTIVE_CHAT_EDIT_BOX = nil;
|
|
end);
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnMouseUp", function(self, button)
|
|
_G.CloseDropDownMenus();
|
|
if(button == "RightButton") then
|
|
PopContextMenu("MENU_MSGBOX", self);
|
|
else
|
|
-- DisplayTutorial(L["Right-Mouse Click!"], L["There might be useful tools hidden under the message box. Right-Click to see them!"]);
|
|
end
|
|
end);
|
|
RegisterWidgetTrigger("msg_box", "whisper,chat,w2w", "OnMouseDown", function(self, button)
|
|
MSG_CONTEXT_MENU_EDITBOX = self;
|
|
end);
|
|
|
|
RegisterWidgetTrigger("msg_box", "whisper,w2w", "OnTabPressed", function(self)
|
|
if(db.tabAdvance and not _G.IsShiftKeyDown()) then
|
|
-- Get the current whisper target
|
|
local win = getParentMessageWindow(self)
|
|
local whisperTarget = win.isBN and win.toonName or win.theUser
|
|
local chatType = win.isBN and "BN_WHISPER" or "WHISPER"
|
|
-- Lookup the next whisper target
|
|
local nextWhisperTarget = _G.ChatEdit_GetNextTellTarget(whisperTarget,chatType)
|
|
|
|
if nextWhisperTarget ~= "" then
|
|
local win = GetWhisperWindowByUser(nextWhisperTarget);
|
|
chatType = win.isBN and "BN_WHISPER" or "WHISPER"
|
|
win:Hide();
|
|
win:Pop(true); -- force popup
|
|
win.widgets.msg_box:SetFocus();
|
|
_G.ChatEdit_SetLastTellTarget(nextWhisperTarget,chatType);
|
|
end
|
|
end
|
|
end);
|
|
|
|
|
|
-- handle formatting options.
|
|
local function applyBracket(index)
|
|
if(db.formatting.bracketing.enabled) then
|
|
local tbl = lists.bracketing[db.formatting.bracketing.type];
|
|
return tbl[(index or 1)];
|
|
else
|
|
return "";
|
|
end
|
|
end
|
|
|
|
RegisterMessageFormatting(L["Default"], function(smf, event, ...)
|
|
local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 = ...;
|
|
arg11 = arg11 or 0;
|
|
local doColoredNames = constants.classes.GetColoredNameByChatEvent;
|
|
if(event == "CHAT_MSG_WHISPER") then
|
|
return applyBracket().."|Hplayer:"..arg2..":"..arg11.."|h"..(db.coloredNames and doColoredNames(event, ...) or arg2).."|h"..applyBracket(2)..": "..arg1;
|
|
elseif(event == "CHAT_MSG_WHISPER_INFORM") then
|
|
arg11 = arg11 or 0;
|
|
return applyBracket().."|Hplayer:".._G.UnitName("player")..":"..arg11.."|h"..(db.coloredNames and constants.classes.GetMyColoredName() or _G.UnitName("player")).."|h"..applyBracket(2)..": "..arg1;
|
|
elseif(event == "CHAT_MSG_BN_WHISPER") then
|
|
local win = smf.parentWindow;
|
|
local color;
|
|
if(win.bn.client == _G.BNET_CLIENT_WOW and constants.classes[win.bn.class] and constants.classes[win.bn.class].color) then
|
|
color = constants.classes[win.bn.class].color
|
|
color = string.len(color) == 6 and color or nil;
|
|
end
|
|
return applyBracket().."|HBNplayer:"..arg2..":"..arg11.."|h"..(db.coloredNames and color and "|cff"..color..arg2.."|r" or arg2).."|h"..applyBracket(2)..": "..arg1;
|
|
elseif(event == "CHAT_MSG_BN_WHISPER_INFORM") then
|
|
arg11 = arg11 or 0;
|
|
return applyBracket().."|Hplayer:".._G.UnitName("player")..":"..arg11.."|h"..(db.coloredNames and constants.classes.GetMyColoredName() or _G.UnitName("player")).."|h"..applyBracket(2)..": "..arg1;
|
|
elseif(event == "CHAT_MSG_AFK") then
|
|
return _G.format(L["%s is Away From Keyboard: %s"], applyBracket().."|Hplayer:"..arg2..":"..arg11.."|h"..arg2.."|h"..applyBracket(2), arg1);
|
|
elseif(event == "CHAT_MSG_DND") then
|
|
return _G.format(L["%s does not wish to be disturbed: %s"], applyBracket().."|Hplayer:"..arg2..":"..arg11.."|h"..arg2.."|h"..applyBracket(2), arg1);
|
|
elseif(event == "CHAT_MSG_GUILD" or event == "CHAT_MSG_OFFICER" or event == "CHAT_MSG_PARTY" or
|
|
event == "CHAT_MSG_RAID" or event == "CHAT_MSG_RAID_LEADER" or event == "CHAT_MSG_SAY" or event == "CHAT_MSG_PARTY_LEADER" or
|
|
event == "CHAT_MSG_CHANNEL" or event == "CHAT_MSG_INSTANCE_CHAT" or event == "CHAT_MSG_INSTANCE_CHAT_LEADER") then
|
|
return applyBracket().."|Hplayer:"..arg2..":"..arg11.."|h"..(db.coloredNames and doColoredNames(event, ...) or arg2).."|h"..applyBracket(2)..": "..arg1;
|
|
elseif(event == "CHAT_MSG_EMOTE") then
|
|
return "|Hplayer:"..arg2..":"..arg11.."|h"..(db.coloredNames and doColoredNames(event, ...) or arg2).."|h".." "..arg1;
|
|
elseif(event == "CHAT_MSG_TEXT_EMOTE") then
|
|
local user = "|Hplayer:"..arg2..":"..arg11.."|h"..(db.coloredNames and doColoredNames(event, ...) or arg2).."|h"
|
|
return arg1;
|
|
elseif(event == "CHAT_MSG_RAID_WARNING") then
|
|
return _G.RAID_WARNING.." "..applyBracket().."|Hplayer:"..arg2..":"..arg11.."|h"..(db.coloredNames and doColoredNames(event, ...) or arg2).."|h"..applyBracket(2)..": "..arg1;
|
|
elseif(event == "CHAT_MSG_CHANNEL_JOIN") then
|
|
return string.format(_G.CHAT_CHANNEL_JOIN_GET, arg2);
|
|
elseif(event == "CHAT_MSG_CHANNEL_LEAVE") then
|
|
return string.format(_G.CHAT_CHANNEL_LEAVE_GET, arg2);
|
|
elseif(event == "CHAT_MSG_CHANNEL_NOTICE_USER") then
|
|
if(_G.strlen(arg5) > 0) then
|
|
-- TWO users in this notice (E.G. x kicked y)
|
|
return _G.format(_G["CHAT_"..arg1.."_NOTICE"], arg8, arg4, arg2, arg5);
|
|
elseif ( arg1 == "INVITE" ) then
|
|
return _G.format(_G["CHAT_"..arg1.."_NOTICE"], arg4, arg2);
|
|
else
|
|
return _G.format(_G["CHAT_"..arg1.."_NOTICE"], arg8, arg4, arg2);
|
|
end
|
|
elseif(event == "CHAT_MSG_CHANNEL_NOTICE") then
|
|
return _G.format(_G["CHAT_"..arg1.."_NOTICE"], arg8, arg4);
|
|
else
|
|
return "Unknown event received...";
|
|
end
|
|
end);
|
|
|
|
|
|
|
|
-- handle escape to close windows
|
|
local escapeFrame = CreateFrame("Frame", "WIM_SpecialWindowMonitor")
|
|
table.insert(_G.UISpecialFrames, "WIM_SpecialWindowMonitor");
|
|
escapeFrame.Hide = function(self)
|
|
if(WindowParent.animUp or not (db and db.escapeToHide)) then
|
|
return nil; -- don't close windows if WindowParent is in use.
|
|
end
|
|
-- lets do some checks first shall we?
|
|
local stack = _G.debugstack(1);
|
|
if(stack:match("TOGGLEWORLDMAP")) then
|
|
-- we do not want to close the windows.
|
|
return;
|
|
elseif(stack:match("UIParent_OnEvent")) then
|
|
-- need some checks here. we want to close the windows at some point...
|
|
return;
|
|
end
|
|
for i=1, #WindowSoupBowl.windows do
|
|
local win = WindowSoupBowl.windows[i].obj;
|
|
if(win:IsShown()) then
|
|
win:Hide();
|
|
end
|
|
end
|
|
end
|
|
escapeFrame.IsShown = function(self)
|
|
if(WindowParent.animUp or not (db and db.escapeToHide)) then
|
|
return nil; -- don't close windows if WindowParent is in use.
|
|
end
|
|
for i=1, #WindowSoupBowl.windows do
|
|
local win = WindowSoupBowl.windows[i].obj;
|
|
if(win:IsVisible()) then
|
|
return 1;
|
|
end
|
|
end
|
|
return nil;
|
|
end
|
|
escapeFrame:Show();
|
|
|
|
|
|
-- define context menu
|
|
local info = _G.UIDropDownMenu_CreateInfo();
|
|
info.text = "MENU_MSGBOX";
|
|
local msgBoxMenu = AddContextMenu(info.text, info);
|
|
local info = _G.UIDropDownMenu_CreateInfo();
|
|
info.text = _G.CANCEL;
|
|
info.notCheckable = true;
|
|
info.func = function() _G.CloseDropDownMenus(); end
|
|
msgBoxMenu:AddSubItem(AddContextMenu("MENU_CANCEL", info));
|
|
|