-- ------------------------------------------------------------------------------ -- -- TradeSkillMaster -- -- https://tradeskillmaster.com -- -- All Rights Reserved - Detailed license information included with addon. -- -- ------------------------------------------------------------------------------ -- --- Theme Functions. -- @module Theme local _, TSM = ... local Theme = TSM.Init("Util.Theme") local FontPaths = TSM.Include("Data.FontPaths") local Table = TSM.Include("Util.Table") local Color = TSM.Include("Util.Color") local FontObject = TSM.Include("Util.FontObject") local private = { callbacks = {}, names = {}, colorSets = {}, currentColorSet = nil, fontFrame = nil, currentFontSet = nil, } local THEME_COLOR_KEYS = { FRAME_BG = true, PRIMARY_BG = true, PRIMARY_BG_ALT = true, ACTIVE_BG = true, ACTIVE_BG_ALT = true, } local STATIC_COLORS = { INDICATOR = Color.NewFromHex("#ffd839"), INDICATOR_ALT = Color.NewFromHex("#79a2ff"), INDICATOR_DISABLED = Color.NewFromHex("#6f5819"), TEXT = Color.NewFromHex("#ffffff"), TEXT_ALT = Color.NewFromHex("#e2e2e2"), TEXT_DISABLED = Color.NewFromHex("#424242"), } local FEEDBACK_COLORS = { RED = Color.NewFromHex("#f72d20"), YELLOW = Color.NewFromHex("#e1f720"), GREEN = Color.NewFromHex("#4ff720"), BLUE = Color.NewFromHex("#2076f7"), ORANGE = Color.NewFromHex("#f77a20"), } local BLIZZARD_COLOR = Color.NewFromHex("#00b4ff") local GROUP_COLORS = { Color.NewFromHex("#fcf141"), Color.NewFromHex("#bdaec6"), Color.NewFromHex("#06a2cb"), Color.NewFromHex("#ffb85c"), Color.NewFromHex("#51b599"), } local PROFESSION_DIFFICULTY_COLORS = { optimal = Color.NewFromHex("#ff8040"), medium = Color.NewFromHex("#ffff00"), easy = Color.NewFromHex("#40c040"), trivial = Color.NewFromHex("#808080"), header = Color.NewFromHex("#ffd100"), subheader = Color.NewFromHex("#ffd100"), nodifficulty = Color.NewFromHex("#f5f5f5"), } -- NOTE: there is a global ITEM_QUALITY_COLORS so we need to use another name local TSM_ITEM_QUALITY_COLORS = { [0] = Color.NewFromHex("#9d9d9d"), [1] = Color.NewFromHex("#ffffff"), [2] = Color.NewFromHex("#1eff00"), [3] = Color.NewFromHex("#0070dd"), [4] = Color.NewFromHex("#a334ee"), [5] = Color.NewFromHex("#ff8000"), [6] = Color.NewFromHex("#e6cc80"), [7] = Color.NewFromHex("#00ccff"), [8] = Color.NewFromHex("#00ccff"), } local AUCTION_PCT_COLORS = { { -- blue color = "BLUE", value = 50, }, { -- green color = "GREEN", value = 80, }, { -- yellow color = "YELLOW", value = 110, }, { -- orange color = "ORANGE", value = 135, }, { -- red color = "RED", value = math.huge, }, default = "TEXT", bid = "TEXT_ALT", } local CONSTANTS = { COL_SPACING = 8, SCROLLBAR_MARGIN = 4, SCROLLBAR_WIDTH = 4, MOUSE_WHEEL_SCROLL_AMOUNT = 60, } -- ============================================================================ -- Module Loading -- ============================================================================ Theme:OnModuleLoad(function() Table.SetReadOnly(STATIC_COLORS) Table.SetReadOnly(FEEDBACK_COLORS) Table.SetReadOnly(GROUP_COLORS) Table.SetReadOnly(PROFESSION_DIFFICULTY_COLORS) Table.SetReadOnly(TSM_ITEM_QUALITY_COLORS) Table.SetReadOnly(CONSTANTS) -- create a frame to load fonts private.fontFrame = CreateFrame("Frame", nil, UIParent) private.fontFrame.texts = {} private.fontFrame:SetAllPoints() private.fontFrame:SetScript("OnUpdate", private.FontFrameOnUpdate) -- TODO: eventually allow for different font sets? private.currentFontSet = { HEADING_H5 = FontObject.New(FontPaths.GetBodyRegular(), 20, 28), BODY_BODY1 = FontObject.New(FontPaths.GetBodyRegular(), 16, 24), BODY_BODY1_BOLD = FontObject.New(FontPaths.GetBodyBold(), 16, 24), BODY_BODY2 = FontObject.New(FontPaths.GetBodyRegular(), 14, 20), BODY_BODY2_MEDIUM = FontObject.New(FontPaths.GetBodyMedium(), 14, 20), BODY_BODY2_BOLD = FontObject.New(FontPaths.GetBodyBold(), 14, 20), BODY_BODY3 = FontObject.New(FontPaths.GetBodyRegular(), 12, 20), BODY_BODY3_MEDIUM = FontObject.New(FontPaths.GetBodyMedium(), 12, 20), ITEM_BODY1 = FontObject.New(FontPaths.GetItem(), 16, 24), ITEM_BODY2 = FontObject.New(FontPaths.GetItem(), 14, 20), ITEM_BODY3 = FontObject.New(FontPaths.GetItem(), 12, 20), TABLE_TABLE1 = FontObject.New(FontPaths.GetTable(), 12, 20), } -- load the fonts for _, obj in pairs(private.currentFontSet) do local fontPath = obj:GetWowFont() private.QueueFontLoad(fontPath) end end) -- ============================================================================ -- Module Functions -- ============================================================================ --- Registers a callback when the theme changes. -- @tparam function callback The callback function function Theme.RegisterChangeCallback(callback) assert(type(callback) == "function") tinsert(private.callbacks, callback) end --- Registers a new color set. -- @tparam string key The key which represents the color set -- @tparam string name The name of the color set -- @tparam table colorSet The colors which make up the color set (with keys specified in `THEME_COLOR_KEYS`) function Theme.RegisterColorSet(key, name, colorSet) assert(not private.colorSets[key]) for k in pairs(THEME_COLOR_KEYS) do assert(Color.IsInstance(colorSet[k])) end private.names[key] = name private.colorSets[key] = colorSet end --- Sets the active color set. -- @tparam string key The key which represents the color set function Theme.SetActiveColorSet(key) assert(private.colorSets[key]) if private.currentColorSet == private.colorSets[key] then return end private.currentColorSet = private.colorSets[key] for _, callback in ipairs(private.callbacks) do callback() end end function Theme.GetThemeName(key) return private.names[key] end --- Gets the color object from the current active color set. -- @tparam string key The key of the color to get -- @treturn Color The color object function Theme.GetColor(key, themeKey) local colorKey, tintPct, opacityPct = strmatch(key, "^([A-Z_]+)([%-%+]?[0-9A-Z_]*)%%?([0-9A-Z_]*)$") tintPct = tonumber(tintPct) or (tintPct ~= "" and tintPct or nil) opacityPct = tonumber(opacityPct) or (opacityPct ~= "" and opacityPct or nil) assert(colorKey) local color = nil if THEME_COLOR_KEYS[colorKey] then color = themeKey and private.colorSets[themeKey][colorKey] or private.currentColorSet[colorKey] else color = STATIC_COLORS[colorKey] end assert(color) if tintPct then color = color:GetTint(tintPct) end if opacityPct then color = color:GetOpacity(opacityPct) end return color end --- Gets the color object for a given feedback color key. -- @tparam string key The key of the feedback color to get -- @treturn Color The color object function Theme.GetFeedbackColor(key) return FEEDBACK_COLORS[key] end --- Gets the color object for Blizzard GMs. -- @treturn Color The color object function Theme.GetBlizzardColor() return BLIZZARD_COLOR end --- Gets the color object for a given group level. -- @tparam number level The level of the group (1-based) -- @treturn Color The color object function Theme.GetGroupColor(level) level = ((level - 1) % #GROUP_COLORS) + 1 return GROUP_COLORS[level] end function Theme.GetProfessionDifficultyColor(difficulty) return PROFESSION_DIFFICULTY_COLORS[difficulty] end function Theme.GetItemQualityColor(quality) return TSM_ITEM_QUALITY_COLORS[quality] end function Theme.GetAuctionPercentColor(pct) if pct == "BID" then return Theme.GetColor(AUCTION_PCT_COLORS.bid) end for _, info in ipairs(AUCTION_PCT_COLORS) do if pct < info.value then return Theme.GetFeedbackColor(info.color) end end return Theme.GetColor(AUCTION_PCT_COLORS.default) end --- Gets the font object from the current active font set. -- @tparam string key The key of the font to get -- @treturn FontObject The font object function Theme.GetFont(key) local fontObj = private.currentFontSet[key] assert(fontObj) return fontObj end --- Gets the column spacing constant value. -- @treturn number The column spacing function Theme.GetColSpacing() return CONSTANTS.COL_SPACING end --- Gets the scrollbar margin constant value. -- @treturn number The scrollbar margin function Theme.GetScrollbarMargin() return CONSTANTS.SCROLLBAR_MARGIN end --- Gets the scrollbar width constant value. -- @treturn number The scrollbar width function Theme.GetScrollbarWidth() return CONSTANTS.SCROLLBAR_WIDTH end --- Gets the scrollbar width constant value. -- @treturn number The scrollbar width function Theme.GetMouseWheelScrollAmount() return CONSTANTS.MOUSE_WHEEL_SCROLL_AMOUNT end -- ============================================================================ -- Private Helper Functions -- ============================================================================ function private.QueueFontLoad(path) if private.fontFrame.texts[path] then return end local fontString = private.fontFrame:CreateFontString() fontString:SetPoint("CENTER") fontString:SetWidth(10000) fontString:SetHeight(6) fontString:SetFont(path, 6) fontString:SetText("1") private.fontFrame.texts[path] = fontString private.fontFrame:Show() end function private.FontFrameOnUpdate(frame) for _, fontString in pairs(frame.texts) do if fontString:IsVisible() then assert(fontString:GetStringWidth() > 0, "Text not loaded: "..tostring(fontString:GetFont())) fontString:Hide() end end frame:Hide() end