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.

393 lines
15 KiB

local WIM = WIM;
-- imports
local _G = _G;
local table = table;
local pairs = pairs;
local string = string;
local debugstack = debugstack;
local type = type;
local unpack = unpack;
local setmetatable = setmetatable;
local getmetatable = getmetatable;
local rawget = rawget;
-- set namespace
setfenv(1, WIM);
db_defaults.skin = {
selected = "WIM Classic",
font = "ChatFontNormal",
font_outline = "",
suggest = true,
};
local SelectedSkin;
local SKIN_DEBUG = "";
local SkinTable = {};
local fontTable = {};
local prematureRegisters = {};
local WindowSoupBowl = WIM:GetWindowSoupBowl();
local function linkSkinTable(src, dest)
if(type(src) == "table") then
if(type(dest) ~= "table") then dest = {}; end
--clear current meta table if there is one.
setmetatable(dest, nil);
for k, v in pairs(src) do
if(not (k == "points" and type(dest[k]) == "table") and type(v) == "table") then
linkSkinTable(v, dest[k]);
end
end
--setmetatable
setmetatable(dest, {__index = src});
end
end
local function setPointsToObj(obj, pointsTable)
obj:ClearAllPoints();
local i;
for i=1, #pointsTable do
local point, relativeTo, relativePoint, offx, offy = unpack(pointsTable[i]);
-- first we need to convert the string representation of objects into actual objects.
if(relativeTo and type(relativeTo) == "string") then
if(string.lower(relativeTo) == "window") then
relativeTo = obj.parentWindow;
else
relativeTo = obj.parentWindow.widgets[relativeTo];
end
relativeTo = relativeTo or UIPanel;
end
-- set the actual points
obj:SetPoint(point, relativeTo, relativePoint, offx, offy);
end
end
-- load selected skin
function ApplySkinToWindow(obj)
local fName = obj:GetName();
local SelectedSkin = WIM:GetSelectedSkin();
obj:SetMinResize(SelectedSkin.message_window.min_width, SelectedSkin.message_window.min_height);
--set backdrop edges and background textures.
local tl = obj.widgets.Backdrop.tl;
tl:SetTexture(SelectedSkin.message_window.texture);
tl:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.top_left.texture_coord));
tl:ClearAllPoints();
tl:SetPoint("TOPLEFT", fName.."Backdrop", "TOPLEFT", unpack(SelectedSkin.message_window.backdrop.top_left.offset));
tl:SetWidth(SelectedSkin.message_window.backdrop.top_left.width);
tl:SetHeight(SelectedSkin.message_window.backdrop.top_left.height);
local tr = obj.widgets.Backdrop.tr;
tr:SetTexture(SelectedSkin.message_window.texture);
tr:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.top_right.texture_coord));
tr:ClearAllPoints();
tr:SetPoint("TOPRIGHT", fName.."Backdrop", "TOPRIGHT", unpack(SelectedSkin.message_window.backdrop.top_right.offset));
tr:SetWidth(SelectedSkin.message_window.backdrop.top_right.width);
tr:SetHeight(SelectedSkin.message_window.backdrop.top_right.height);
local bl = obj.widgets.Backdrop.bl;
bl:SetTexture(SelectedSkin.message_window.texture);
bl:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.bottom_left.texture_coord));
bl:ClearAllPoints();
bl:SetPoint("BOTTOMLEFT", fName.."Backdrop", "BOTTOMLEFT", unpack(SelectedSkin.message_window.backdrop.bottom_left.offset));
bl:SetWidth(SelectedSkin.message_window.backdrop.bottom_left.width);
bl:SetHeight(SelectedSkin.message_window.backdrop.bottom_left.height);
local br = obj.widgets.Backdrop.br;
br:SetTexture(SelectedSkin.message_window.texture);
br:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.bottom_right.texture_coord));
br:ClearAllPoints();
br:SetPoint("BOTTOMRIGHT", fName.."Backdrop", "BOTTOMRIGHT", unpack(SelectedSkin.message_window.backdrop.bottom_right.offset));
br:SetWidth(SelectedSkin.message_window.backdrop.bottom_right.width);
br:SetHeight(SelectedSkin.message_window.backdrop.bottom_right.height);
local t = obj.widgets.Backdrop.t;
t:SetTexture(SelectedSkin.message_window.texture, SelectedSkin.message_window.backdrop.top.tile or nil);
t:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.top.texture_coord));
t:ClearAllPoints();
t:SetPoint("TOPLEFT", fName.."Backdrop_TL", "TOPRIGHT", 0, 0);
t:SetPoint("BOTTOMRIGHT", fName.."Backdrop_TR", "BOTTOMLEFT", 0, 0);
local b = obj.widgets.Backdrop.b;
b:SetTexture(SelectedSkin.message_window.texture, SelectedSkin.message_window.backdrop.bottom.tile or nil);
b:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.bottom.texture_coord));
b:ClearAllPoints();
b:SetPoint("TOPLEFT", fName.."Backdrop_BL", "TOPRIGHT", 0, 0);
b:SetPoint("BOTTOMRIGHT", fName.."Backdrop_BR", "BOTTOMLEFT", 0, 0);
local l = obj.widgets.Backdrop.l;
l:SetTexture(SelectedSkin.message_window.texture, SelectedSkin.message_window.backdrop.left.tile or nil);
l:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.left.texture_coord));
l:ClearAllPoints();
l:SetPoint("TOPLEFT", fName.."Backdrop_TL", "BOTTOMLEFT", 0, 0);
l:SetPoint("BOTTOMRIGHT", fName.."Backdrop_BL", "TOPRIGHT", 0, 0);
local r = obj.widgets.Backdrop.r;
r:SetTexture(SelectedSkin.message_window.texture, SelectedSkin.message_window.backdrop.right.tile or nil);
r:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.right.texture_coord));
r:ClearAllPoints();
r:SetPoint("TOPLEFT", fName.."Backdrop_TR", "BOTTOMLEFT", 0, 0);
r:SetPoint("BOTTOMRIGHT", fName.."Backdrop_BR", "TOPRIGHT", 0, 0);
local bg = obj.widgets.Backdrop.bg;
bg:SetTexture(SelectedSkin.message_window.texture, SelectedSkin.message_window.backdrop.background.tile or nil);
bg:SetTexCoord(unpack(SelectedSkin.message_window.backdrop.background.texture_coord));
bg:ClearAllPoints();
bg:SetPoint("TOPLEFT", fName.."Backdrop_TL", "BOTTOMRIGHT", 0, 0);
bg:SetPoint("BOTTOMRIGHT", fName.."Backdrop_BR", "TOPLEFT", 0, 0);
--set class icon
local class_icon = obj.widgets.class_icon;
ApplySkinToWidget(class_icon);
class_icon:SetTexture(SelectedSkin.message_window.widgets.class_icon.texture);
--WIM_UpdateMessageWindowClassIcon(obj);
--set from font
local from = obj.widgets.from;
ApplySkinToWidget(from);
--set character details font
local char_info = obj.widgets.char_info;
ApplySkinToWidget(char_info);
--close button
local close = obj.widgets.close;
ApplySkinToWidget(close);
-- close button is a special case... so do the following extra work.
if(close.curTextureIndex == 1) then
close:SetNormalTexture(SelectedSkin.message_window.widgets.close.state_hide.NormalTexture);
close:SetPushedTexture(SelectedSkin.message_window.widgets.close.state_hide.PushedTexture);
close:SetHighlightTexture(SelectedSkin.message_window.widgets.close.state_hide.HighlightTexture, SelectedSkin.message_window.widgets.close.state_hide.HighlightAlphaMode);
else
close:SetNormalTexture(SelectedSkin.message_window.widgets.close.state_close.NormalTexture);
close:SetPushedTexture(SelectedSkin.message_window.widgets.close.state_close.PushedTexture);
close:SetHighlightTexture(SelectedSkin.message_window.widgets.close.state_close.HighlightTexture, SelectedSkin.message_window.widgets.close.state_close.HighlightAlphaMode);
end
--scroll_up button
local scroll_up = obj.widgets.scroll_up;
ApplySkinToWidget(scroll_up);
--scroll_down button
local scroll_down = obj.widgets.scroll_down;
ApplySkinToWidget(scroll_down);
--chat display
local chat_display = obj.widgets.chat_display;
ApplySkinToWidget(chat_display);
local font, height, flags;
if(not db.skin.suggest) then
if(_G[db.skin.font]) then
font, height, flags = _G[db.skin.font]:GetFont();
else
font = libs.SML.MediaTable.font[db.skin.font] or _G["ChatFontNormal"]:GetFont();
end
chat_display:SetFont(font, db.fontSize+2, db.skin.font_outline);
end
--msg_box
local msg_box = obj.widgets.msg_box;
ApplySkinToWidget(msg_box);
if(not db.skin.suggest) then
msg_box:SetFont(font, SelectedSkin.message_window.widgets.msg_box.font_height, WIM.db.skin.font_outline);
end
--msg_box:SetTextColor(SelectedSkin.message_window.widgets.msg_box.font_color[1], SelectedSkin.message_window.widgets.msg_box.font_color[2], SelectedSkin.message_window.widgets.msg_box.font_color[3]);
--apply skin to registered widgets
for widget, _ in pairs(windows.widgets) do
if(obj.widgets[widget] and SelectedSkin.message_window.widgets[widget]) then
dPrint("Applying skin to '"..widget.."'.");
ApplySkinToWidget(obj.widgets[widget]);
end
end
obj:UpdateProps();
obj:UpdateIcon();
obj:UpdateCharDetails();
end
local function deleteStyleFileEntries(theTable)
if(type(theTable) == "table") then
for key, _ in pairs(theTable) do
theTable[key] = nil;
end
end
end
function RegisterPrematureSkins()
for i=1,#prematureRegisters do
RegisterSkin(prematureRegisters[i]);
end
end
function GetSelectedSkin()
return SelectedSkin or SkinTable["WIM Classic"];
end
function LoadSkin(skinName)
if(skinName == nil or (not SkinTable[skinName])) then
skinName = "WIM Classic";
end
SelectedSkin = SkinTable[skinName];
db.skin.selected = skinName;
SKIN_DEBUG = SKIN_DEBUG..skinName.." loaded..\n";
-- apply skin to window objects
local window_objects = WindowSoupBowl.windows;
for i=1, table.getn(window_objects) do
ApplySkinToWindow(window_objects[i].obj);
end
end
function RegisterFont(objName, title)
if(objName == nil or objName == "") then
return;
end
if(title == nil or title == "") then
title = objName
end
if(getglobal(objName)) then
fontTable[objName] = title;
else
DEFAULT_CHAT_FRAME:AddMessage("WIM SKIN ERROR: Registered font object does not exist!");
end
end
function RegisterSkin(skinTable)
if(not isInitialized) then
table.insert(prematureRegisters, skinTable);
return;
end
local required = {"title", "author", "version"};
local error_list = "";
local addonName;
local stack = {string.split("\n", debugstack())};
if(table.getn(stack) >= 2) then
local paths = {string.split("\\", stack[2])};
addonName = paths[3];
else
addonName = "Unknown";
end
for i=1,table.getn(required) do
if(skinTable[required[i]] == nil or skinTable[required[i]] == "") then error_list = error_list.."- Required field '"..required[i].."' was not defined.\n"; end
end
if(error_list ~= "") then
SKIN_DEBUG = SKIN_DEBUG.."\n\n---------------------------------------------------------\nSKIN ERROR FROM: "..addonName.."\n---------------------------------------------------------\n";
SKIN_DEBUG = SKIN_DEBUG.."Skin was not loaded for the following reason(s):\n\n"..error_list.."\n\n";
return;
end
if(skinTable.title == "WIM Classic") then
SkinTable[skinTable.title] = skinTable;
if(skinTable.title == db.skin.selected) then
LoadSkin(WIM.db.skin.selected);
end
return; -- this is the main skin, we don't need to do anything further...
end
-- inherrit missing data from default skin.
linkSkinTable(SkinTable["WIM Classic"], skinTable);
-- finalize registration
SkinTable[skinTable.title] = skinTable;
-- if this is the selected skin, load it now
if(skinTable.title == WIM.db.skin.selected) then
LoadSkin(WIM.db.skin.selected, WIM.db.skin);
end
end
function GetFontKeyByName(fontName)
for key, val in pairs(fontTable) do
if(val == fontName) then
return key;
end
end
return nil;
end
function SetWidgetFont(obj, widgetSkinTable)
-- first check what font is being requested, height is applied here.
if(widgetSkinTable.font) then
if(_G[widgetSkinTable.font]) then
-- font is to be inherrited
obj:SetFontObject(_G[widgetSkinTable.font]);
local font, height, flags = _G[widgetSkinTable.font]:GetFont();
obj:SetFont(font, widgetSkinTable.font_height or height, widgetSkinTable.font_flags or flags);
elseif(libs.SML.MediaTable.font[widgetSkinTable.font]) then
obj:SetFont(libs.SML.MediaTable.font[widgetSkinTable.font], widgetSkinTable.font_height or 12, widgetSkinTable.font_flags or "");
else
-- can't find font, load a default font.
local font, height, flags = _G["ChatFontNormal"]:GetFont();
obj:SetFont(font, widgetSkinTable.font_height or 12, widgetSkinTable.font_flags or "");
end
end
-- next, lets add the extra properties to it.
if(widgetSkinTable.font_color) then
if(type(widgetSkinTable.font_color) == "table") then
obj:SetTextColor(unpack(widgetSkinTable.font_color));
else
obj:SetTextColor(RGBHexToPercent(widgetSkinTable.font_color));
end
end
end
function SetWidgetRect(obj, widgetSkinTable)
if(type(widgetSkinTable) == "table") then
if(type(widgetSkinTable.width) == "number") then
obj:SetWidth(widgetSkinTable.width);
end
if(type(widgetSkinTable.height) == "number") then
obj:SetHeight(widgetSkinTable.height);
end
if(widgetSkinTable.points) then
setPointsToObj(obj, widgetSkinTable.points);
end
end
end
function ApplySkinToWidget(obj)
if(obj.GetObjectType) then
local SelectedSkin = GetSelectedSkin();
local widgetSkin = SelectedSkin.message_window.widgets[obj.widgetName] or obj.defaultSkin;
local oType = obj:GetObjectType();
SetWidgetRect(obj, widgetSkin);
if(oType == "Button" or oType == "CheckButton") then
if(widgetSkin.NormalTexture) then obj:SetNormalTexture(widgetSkin.NormalTexture); end
if(widgetSkin.PushedTexture) then obj:SetPushedTexture(widgetSkin.PushedTexture); end
if(widgetSkin.DisabledTexture) then obj:SetDisabledTexture(widgetSkin.DisabledTexture); end
if(widgetSkin.HighlightTexture) then obj:SetHighlightTexture(widgetSkin.HighlightTexture, widgetSkin.HighlightAlphaMode); end
end
if(oType == "FontString" or oType == "ScrollingMessageFrame" or oType == "EditBox") then
SetWidgetFont(obj, widgetSkin);
end
else
dPrint("Invalid widget trying to be skinned.");
end
if(obj.UpdateSkin) then
obj:UpdateSkin();
end
end
function GetSkinTable(skinName)
return SkinTable[skinName];
end
function GetRegisteredSkins()
-- this function isn't called much so its ok to create a little garbage.
local list = {};
for skin, _ in pairs(SkinTable) do
table.insert(list, skin);
end
table.sort(list);
return list;
end