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(); 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(); if obj.SetResizeBounds then -- WoW 10.0 obj:SetResizeBounds(SelectedSkin.message_window.min_width, SelectedSkin.message_window.min_height); else obj:SetMinResize(SelectedSkin.message_window.min_width, SelectedSkin.message_window.min_height); end --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