-- ------------------------------------------------------------------------------ -- -- TradeSkillMaster -- -- http://www.curse.com/addons/wow/tradeskill-master -- -- -- -- A TradeSkillMaster Addon (http://tradeskillmaster.com) -- -- All Rights Reserved* - Detailed license information included with addon. -- -- ------------------------------------------------------------------------------ -- -- This file contains all the code for the stuff that shows under the "Status" icon in the main TSM window. local TSM = select(2, ...) local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster") -- loads the localization table local AceGUI = LibStub("AceGUI-3.0") -- load the AceGUI libraries local LSM = LibStub("LibSharedMedia-3.0") -- load the SharedMedia library local lib = TSMAPI local private = {} TSMAPI:RegisterForTracing(private, "TradeSkillMaster.Options_private") local presetThemes = { light = { L["Light (by Ravanys - The Consortium)"], "inlineColors{link{49,56,133,1}link2{153,255,255,1}category{36,106,36,1}category2{85,180,8,1}}textColors{iconRegion{enabled{105,105,105,1}}title{enabled{49,56,85,1}}label{enabled{45,44,40,1}disabled{150,148,140,1}}text{enabled{245,244,240,1}disabled{95,98,90,1}}link{enabled{49,56,133,1}}}fontSizes{normal{15}medium{13}small{12}}edgeSize{1.5}frameColors{frameBG{backdrop{219,219,219,1}border{30,30,30,1}}content{backdrop{60,60,60,1}border{40,40,40,1}}frame{backdrop{228,228,228,1}border{199,199,199,1}}}" }, goblineer = { L["Goblineer (by Sterling - The Consortium)"], "inlineColors{link{153,255,255,1}link2{153,255,255,1}category{36,106,36,1}category2{85,180,8,1}}textColors{iconRegion{enabled{249,255,247,1}}title{enabled{132,219,9,1}}label{enabled{216,225,211,1}disabled{150,148,140,1}}text{enabled{255,254,250,1}disabled{147,151,139,1}}link{enabled{49,56,133,1}}}fontSizes{normal{15}medium{13}small{12}}edgeSize{1.5}frameColors{frameBG{backdrop{24,24,24,0.93}border{30,30,30,1}}content{backdrop{42,42,42,1}border{0,0,0,0}}frame{backdrop{24,24,24,1}border{255,255,255,0.03}}}" }, jaded = { L["Jaded (by Ravanys - The Consortium)"], "frameColors{frameBG{backdrop{0,0,0,0.6}border{0,0,0,0.4}}content{backdrop{62,62,62,1}border{72,72,72,1}}frame{backdrop{32,32,32,1}border{2,2,2,0.48}}}textColors{text{enabled{99,219,136,1}disabled{95,98,90,1}}iconRegion{enabled{43,255,156,1}}title{enabled{75,255,150,1}}label{enabled{99,219,136,1}disabled{177,176,168,1}}}edgeSize{1}fontSizes{normal{15}medium{13}small{12}}" }, tsmdeck = { L["TSMDeck (by Jim Younkin - Power Word: Gold)"], "inlineColors{link2{153,255,255,1}category2{85,180,8,1}link{89,139,255,1}category{80,222,22,1}}textColors{iconRegion{enabled{117,117,122,1}}title{enabled{247,248,255,1}}label{enabled{238,249,237,1}disabled{110,110,110,1}}text{enabled{245,240,251,1}disabled{115,115,115,1}}link{enabled{49,56,133,1}}}fontSizes{normal{14}medium{13}small{12}}edgeSize{1}frameColors{frameBG{backdrop{29,29,29,1}border{20,20,20,1}}content{backdrop{27,27,27,1}border{67,67,65,1}}frame{backdrop{39,39,40,1}border{20,20,20,1}}}" }, tsmclassic = { L["TSM Classic (by Jim Younkin - Power Word: Gold)"], "inlineColors{link{89,139,255,1}link2{153,255,255,1}category{80,222,22,1}category2{85,180,8,1}}textColors{text{enabled{245,240,251,1}disabled{115,115,115,1}}iconRegion{enabled{216,216,224,1}}title{enabled{247,248,255,1}}label{enabled{238,249,237,1}disabled{110,110,110,1}}}fontSizes{normal{14}medium{13}small{12}}edgeSize{1}frameColors{frameBG{backdrop{8,8,8,1}border{4,2,147,1}}content{backdrop{18,18,18,1}border{102,108,105,1}}frame{backdrop{2,2,2,1}border{4,2,147,1}}}" }, functional = { L["The Functional Gold Maker (by Xsinthis - The Golden Crusade)"], "inlineColors{category{3,175,222,1}link2{153,255,255,1}tooltip{130,130,250}link{89,139,255,1}category2{6,24,180,1}}textColors{iconRegion{enabled{216,216,224,1}}title{enabled{247,248,255,1}}label{enabled{238,249,237,1}disabled{110,110,110,1}}text{enabled{245,240,251,1}disabled{115,115,115,1}}link{enabled{49,56,133,1}}}fontSizes{normal{14}small{12}}edgeSize{0.5}frameColors{frameBG{backdrop{28,28,28,1}border{74,5,0,1}}content{backdrop{18,18,18,0.64000001549721}border{84,7,3,1}}frame{backdrop{2,2,2,0.48000001907349}border{72,9,4,1}}}" }, } local defaultTheme = presetThemes.goblineer function private:LoadHelpPage(parent) local color = lib.Design:GetInlineColor("link") local moduleText = { TSMAPI.Design:ColorText("Accounting", "link") .. " - " .. L["Keeps track of all your sales and purchases from the auction house allowing you to easily track your income and expenditures and make sure you're turning a profit."] .. "\n", TSMAPI.Design:ColorText("Additions", "link") .. " - " .. L["Provides extra functionality that doesn't fit well in other modules."] .. "\n", TSMAPI.Design:ColorText("AuctionDB", "link") .. " - " .. L["Performs scans of the auction house and calculates the market value of items as well as the minimum buyout. This information can be shown in items' tooltips as well as used by other modules."] .. "\n", TSMAPI.Design:ColorText("Auctioning", "link") .. " - " .. L["Posts and cancels your auctions to / from the auction house according to pre-set rules. Also, this module can show you markets which are ripe for being reset for a profit."] .. "\n", TSMAPI.Design:ColorText("Crafting", "link") .. " - " .. L["Allows you to build a queue of crafts that will produce a profitable, see what materials you need to obtain, and actually craft the items."] .. "\n", TSMAPI.Design:ColorText("Destroying", "link") .. " - " .. L["Mills, prospects, and disenchants items at super speed!"] .. "\n", TSMAPI.Design:ColorText("ItemTracker", "link") .. " - " .. L["Tracks and manages your inventory across multiple characters including your bags, bank, and guild bank."] .. "\n", TSMAPI.Design:ColorText("Mailing", "link") .. " - " .. L["Allows you to quickly and easily empty your mailbox as well as automatically send items to other characters with the single click of a button."] .. "\n", TSMAPI.Design:ColorText("Shopping", "link") .. " - " .. L["Provides interfaces for efficiently searching for items on the auction house. When an item is found, it can easily be bought, canceled (if it's yours), or even posted from your bags."] .. "\n", TSMAPI.Design:ColorText("Warehousing", "link") .. " - " .. L["Manages your inventory by allowing you to easily move stuff between your bags, bank, and guild bank."] .. "\n", --TSMAPI.Design:ColorText("WoWuction", "link") .. " - " .. L["Allows you to use data from http://wowuction.com in other TSM modules and view its various price points in your item tooltips."] .. "\n", } local page = { { type = "ScrollFrame", layout = "flow", children = { -- { -- type = "InlineGroup", -- title = L["Resources:"], -- layout = "flow", -- relativeWidth = 1, -- noBorder = true, -- children = { -- { -- type = "Label", -- relativeWidth = .499, -- text = L["Using our website you can get help with TSM, suggest features, and give feedback."].."\n", -- }, -- { -- type = "Image", -- sizeRatio = .15625, -- relativeWidth = .5, -- image = "Interface\\Addons\\TradeSkillMaster\\Media\\banner", -- }, -- { -- type = "HeadingLine" -- }, -- { -- type = "Image", -- sizeRatio = .15628, -- relativeWidth = 1, -- image = "Interface\\Addons\\TradeSkillMaster\\Media\\AppBanner", -- }, -- { -- type = "Label", -- relativeWidth = 1, -- text = format("\n" .. L["Check out our completely free, desktop application which has tons of features including deal notification emails, automatic updating of AuctionDB and WoWuction prices, automatic TSM setting backup, and more! You can find this app by going to %s."], TSMAPI.Design:ColorText("http://tradeskillmaster.com/tsm_app", "link")), -- } -- }, -- }, -- { -- type = "Spacer", -- }, { type = "InlineGroup", title = L["Module Information:"], layout = "List", relativeWidth = 1, noBorder = true, children = {}, }, { type = "InlineGroup", layout = "flow", title = L["TradeSkillMaster Team"], children = { { type = "Label", text = TSMAPI.Design:ColorText(L["Lead Developer and Co-Founder:"], "link") .. " Sapu94 [US-Tichondrius(H)]", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText(L["Application and Addon Developer:"], "link") .. " Bart39 [EU-Darkspear(A)]", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText(L["Web Master:"], "link") .. " Drethic [US-Sentinels(A)]", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText("Logo / Graphic Designer:", "link") .. " Pwnstein", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText(L["Testers (Special Thanks):"], "link") .. " Cryan, GoblinRaset, Mithrildar, PhatLewts, WoWProfitz", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText(L["Past Contributors:"], "link") .. " Geemoney, Mischanix, Xubera, cduhn, cjo20", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText(L["Co-Founder:"], "link") .. " Cente [US-Illidan(H)]", relativeWidth = 1, }, { type = "Label", text = TSMAPI.Design:ColorText(L["Wrath of the Lich King Revival:"], "link") .. " Gnomezilla [Warmane-Icecrown(A)], BlueAo [Warmane], andrew6180, Yoshiyuka, DimaSheiko, and other contributors...", relativeWidth = 1, }, }, }, }, }, } for _, text in ipairs(moduleText) do tinsert(page[1].children[#page[1].children-1].children, { type = "Label", text = text, relativeWidth = 1, }) end lib:BuildPage(parent, page) end local function GetSubStr(str) if not str then return end local startIndex, endIndex local balance = 0 for i = 1, #str do local c = strsub(str, i, i) if c == '{' then if startIndex then balance = balance + 1 else startIndex = i end elseif c == '}' then if balance > 0 then balance = balance - 1 else endIndex = i break end end end if not startIndex or not endIndex then return end return strsub(str, startIndex + 1, endIndex - 1), startIndex, endIndex end local function StringToTable(data) local result = {} while true do local value, s, e = GetSubStr(data, { '{', '}' }) if not value then return end local key = strsub(data, 1, s - 1) value = tonumber(value) or value if type(value) == "string" and strfind(value, "{") then value = StringToTable(value) elseif type(value) == "string" and strfind(value, ",") then value = { (","):split(value) } for i = 1, 4 do value[i] = tonumber(value[i]) end end if type(value) == "nil" then return end result[key] = value if e + 1 > #data then break end data = strsub(data, e + 1, #data) end return result end function TSM:SetDesignDefaults(src, dest) for i, v in pairs(src) do if dest[i] then if type(v) == "table" then TSM:SetDesignDefaults(v, dest[i]) end else if type(v) == "table" then dest[i] = CopyTable(v) else dest[i] = v end end end end local function DecodeAppearanceData(encodedData) if not encodedData then return end -- Decode the appearance-data string into a table. encodedData = gsub(encodedData, " ", "") local result = StringToTable(encodedData, 1) if not result then return TSM:Print(L["Invalid appearance data."]) end -- Preserve the user's current font choices and switch the theme. -- NOTE: The "design" table won't exist on first TSM launch, while we're -- loading the default design, so we also check the "design" table's existence. local preservedFonts = TSM.db.profile.design and TSM.db.profile.design.fonts or nil TSM.db.profile.design = result TSM.db.profile.design.fonts = preservedFonts -- Is allowed to be nil. -- Use default values for any missing fields (such as fonts, if missing). TSM:SetDesignDefaults(TSM.designDefaults, TSM.db.profile.design) -- Apply the new design. TSMAPI:UpdateDesign() end function TSM:LoadDefaultDesign() DecodeAppearanceData(defaultTheme[2]) end local function ShowImportFrame() local data local f = AceGUI:Create("TSMWindow") f:SetCallback("OnClose", function(self) AceGUI:Release(self) end) f:SetTitle("TradeSkillMaster - " .. L["Import Appearance Settings"]) f:SetLayout("Flow") f:SetHeight(200) f:SetHeight(300) local spacer = AceGUI:Create("Label") spacer:SetFullWidth(true) spacer:SetText(" ") f:AddChild(spacer) local btn = AceGUI:Create("TSMButton") local eb = AceGUI:Create("MultiLineEditBox") eb:SetLabel(L["Appearance Data"]) eb:SetFullWidth(true) eb:SetMaxLetters(0) eb:SetCallback("OnEnterPressed", function(_, _, val) btn:SetDisabled(false) data = val end) f:AddChild(eb) btn:SetDisabled(true) btn:SetText(L["Import Appearance Settings"]) btn:SetFullWidth(true) btn:SetCallback("OnClick", function() DecodeAppearanceData(data) f:Hide() end) f:AddChild(btn) f.frame:SetFrameStrata("FULLSCREEN_DIALOG") f.frame:SetFrameLevel(100) end local function TblToStr(tbl) local tmp = {} for key, value in pairs(tbl) do tinsert(tmp, key .. "{") if tonumber(value) then tinsert(tmp, value) elseif #value == 0 then tinsert(tmp, TblToStr(value)) else for _, colorVal in ipairs(value) do tinsert(tmp, tostring(colorVal)) tinsert(tmp, ",") end tremove(tmp, #tmp) end tinsert(tmp, "}") end return table.concat(tmp, "") end local function EncodeAppearanceData() local keys = { "frameColors", "textColors", "inlineColors", "edgeSize", "fontSizes" } local testTbl = {} for _, key in ipairs(keys) do testTbl[key] = TSM.db.profile.design[key] end return TblToStr(testTbl) end local function ShowExportFrame() local f = AceGUI:Create("TSMWindow") f:SetCallback("OnClose", function(self) AceGUI:Release(self) end) f:SetTitle("TradeSkillMaster - " .. L["Export Appearance Settings"]) f:SetLayout("Fill") f:SetHeight(300) local eb = AceGUI:Create("TSMMultiLineEditBox") eb:SetLabel(L["Appearance Data"]) eb:SetMaxLetters(0) eb:SetText(EncodeAppearanceData()) f:AddChild(eb) f.frame:SetFrameStrata("FULLSCREEN_DIALOG") f.frame:SetFrameLevel(100) end function private:LoadOptionsPage(parent) local presetThemeList = {} for key, tbl in pairs(presetThemes) do presetThemeList[key] = tbl[1] end local savedThemeList = {} for _, info in ipairs(TSM.db.profile.savedThemes) do tinsert(savedThemeList, info.name) end local themeName = "" local auctionTabs, auctionTabOrder if AuctionFrame and AuctionFrame.numTabs then auctionTabs, auctionTabOrder = {}, {} for i = 1, AuctionFrame.numTabs do local text = gsub(_G["AuctionFrameTab" .. i]:GetText(), "|r", "") text = gsub(text, "|c[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]", "") auctionTabs[text] = text tinsert(auctionTabOrder, text) end end local characterList = {} for character in pairs(TSMAPI:GetCharacters()) do tinsert(characterList, character) end local chatFrameList = {} local chatFrameValue, defaultValue for i=1, NUM_CHAT_WINDOWS do if DEFAULT_CHAT_FRAME == _G["ChatFrame"..i] then defaultValue = i end local name = strlower(GetChatWindowInfo(i) or "") if name ~= "" then if name == TSM.db.global.chatFrame then chatFrameValue = i end tinsert(chatFrameList, name) end end chatFrameValue = chatFrameValue or defaultValue local page = { { type = "ScrollFrame", layout = "flow", children = { { type = "InlineGroup", layout = "flow", title = L["General Settings"], children = { { type = "CheckBox", label = L["Hide Minimap Icon"], settingInfo = { TSM.db.profile.minimapIcon, "hide" }, relativeWidth = 0.5, callback = function(_, _, value) if value then TSM.LDBIcon:Hide("TradeSkillMaster") else TSM.LDBIcon:Show("TradeSkillMaster") end end, }, { type = "CheckBox", label = L["Color Group Names by Depth"], settingInfo = { TSM.db.profile, "colorGroupName" }, relativeWidth = 0.49, tooltip = L["If checked, group names will be colored based on their subgroup depth in group trees."], }, { type = "CheckBox", label = L["Store Operations Globally"], value = TSM.db.global.globalOperations, relativeWidth = 0.5, callback = function(_, _, value) StaticPopupDialogs["TSM_GLOBAL_OPERATIONS"] = StaticPopupDialogs["TSM_GLOBAL_OPERATIONS"] or { text = L["If you have multiple profile set up with operations, enabling this will cause all but the current profile's operations to be irreversibly lost. Are you sure you want to continue?"], button1 = YES, button2 = CANCEL, timeout = 0, hideOnEscape = true, OnAccept = function() TSM.db.global.globalOperations = value if TSM.db.global.globalOperations then -- move current profile to global TSM.db.global.operations = CopyTable(TSM.db.profile.operations) -- clear out old operations for profile in TSMAPI:GetTSMProfileIterator() do TSM.db.profile.operations = nil end else -- move global to all profiles for profile in TSMAPI:GetTSMProfileIterator() do TSM.db.profile.operations = CopyTable(TSM.db.global.operations) end -- clear out old operations TSM.db.global.operations = nil end TSM:UpdateModuleProfiles() if parent.frame:IsVisible() then parent:ReloadTab() end end, preferredIndex = 3, } parent:ReloadTab() TSMAPI:ShowStaticPopupDialog("TSM_GLOBAL_OPERATIONS") end, tooltip = L["If checked, operations will be stored globally rather than by profile. TSM groups are always stored by profile. Note that if you have multiple profiles setup already with separate operation information, changing this will cause all but the current profile's operations to be lost."], }, { type = "Dropdown", label = L["Forget Characters:"], list = characterList, relativeWidth = 0.49, callback = function(_, _, value) local name = characterList[value] TSM.db.realm.characters[name] = nil TSM:Printf("%s removed.", name) parent:ReloadTab() end, tooltip = L["If you delete, rename, or transfer a character off the current faction/realm, you should remove it from TSM's list of characters using this dropdown."], }, { type = "Dropdown", label = L["Default BankUI Tab"], list = TSM:getBankTabs(), settingInfo = { TSM.db.global, "bankUITab" }, relativeWidth = 0.5, tooltip = L["The default tab shown in the 'BankUI' frame."], }, { type = "Dropdown", label = L["Chat Tab"], list = chatFrameList, value = chatFrameValue, callback = function(_, _, value) TSM.db.global.chatFrame = chatFrameList[value] end, relativeWidth = 0.49, tooltip = L["This option sets which tab TSM and its modules will use for printing chat messages."], }, }, }, { type = "InlineGroup", layout = "flow", title = L["Multi-Account Settings"], children = { { type = "Label", relativeWidth = 1, text = L["Various modules can sync their data between multiple accounts automatically whenever you're logged into both accounts."], }, { type = "Spacer", }, { type = "Label", relativeWidth = 1, text = L["First, log into a character on the same realm (and faction) on both accounts. Type the name of the OTHER character you are logged into in the box below. Once you have done this on both accounts, TSM will do the rest automatically. Once setup, syncing will automatically happen between the two accounts while on any character on the account (not only the one you entered during this setup)."], }, { type = "EditBox", relativeWidth = 1, label = L["Character Name on Other Account"], callback = function(_, _, value) TSM:DoSyncSetup(value:trim()) end, tooltip = L["See instructions above this editbox."], }, { type = "HeadingLine", } }, }, { type = "InlineGroup", layout = "flow", title = L["Auction House Tab Settings"], children = { { type = "Dropdown", label = auctionTabs and L["Default Tab"] or L["Default Tab (Open Auction House to Enable)"], list = auctionTabs or {}, order = auctionTabOrder, disabled = not auctionTabs, settingInfo = { TSM.db.profile, "defaultAuctionTab" }, relativeWidth = 0.5, }, { type = "CheckBox", label = L["Open All Bags with Auction House"], settingInfo = { TSM.db.profile, "openAllBags" }, relativeWidth = 0.5, tooltip = L["If checked, your bags will be automatically opened when you open the auction house."], }, { type = "HeadingLine", }, { type = "CheckBox", label = L["Show Bids in Auction Results Table (Requires Reload)"], settingInfo = { TSM.db.profile, "showBids" }, tooltip = L["If checked, all tables listing auctions will display the bid as well as the buyout of the auctions. This will not take effect immediately and may require a reload."], }, { type = "Slider", label = L["Number of Auction Result Rows (Requires Reload)"], settingInfo = { TSM.db.profile, "auctionResultRows" }, relativeWidth = 0.5, min = 8, max = 25, step = 1, tooltip = L["Changes how many rows are shown in the auction results tables."], }, { type = "HeadingLine", }, { type = "CheckBox", label = L["Make Auction Frame Movable"], settingInfo = { TSM.db.profile, "auctionFrameMovable" }, callback = function(_, _, value) if AuctionFrame then AuctionFrame:SetMovable(value) end end, }, { type = "Slider", label = L["Auction Frame Scale"], settingInfo = { TSM.db.profile, "auctionFrameScale" }, isPercent = true, relativeWidth = 0.5, min = 0.1, max = 2, step = 0.05, callback = function(_, _, value) if AuctionFrame then AuctionFrame:SetScale(value) end end, tooltip = L["Changes the size of the auction frame. The size of the detached TSM auction frame will always be the same as the main auction frame."], }, }, }, { type = "InlineGroup", layout = "flow", title = L["TSM Appearance Options"], children = { { type = "Label", text = L["Use the options below to change and tweak the appearance of TSM."], relativeWidth = 1, }, { type = "Dropdown", label = L["Import Preset TSM Theme"], list = presetThemeList, relativeWidth = 1, callback = function(_, _, key) if presetThemes[key] then DecodeAppearanceData(presetThemes[key][2]) end end, tooltip = L["Select a theme from this dropdown to import one of the preset TSM themes."], }, { type = "Dropdown", label = L["Load Saved Theme"], list = savedThemeList, relativeWidth = 1, callback = function(_, _, index) DecodeAppearanceData(TSM.db.profile.savedThemes[index].theme) end, tooltip = L["Select a theme from this dropdown to import one of your saved TSM themes."], }, { type = "EditBox", label = L["Theme Name"], relativeWidth = 0.5, callback = function(_, _, value) themeName = value:trim() end, }, { type = "Button", text = L["Save Theme"], relativeWidth = 0.5, callback = function(_, _, value) if themeName == "" then return TSM:Print(L["Theme name is empty."]) end TSM:Printf(L["Saved theme: %s."], themeName) tinsert(TSM.db.profile.savedThemes, { name = themeName, theme = EncodeAppearanceData() }) parent:ReloadTab() end, }, { type = "Button", text = L["Restore Default Colors"], relativeWidth = 1, callback = function() TSM:LoadDefaultDesign() parent:ReloadTab() end, tooltip = L["Restores all the color settings below to their default values."], }, { type = "Button", text = L["Import Appearance Settings"], relativeWidth = 0.5, callback = ShowImportFrame, tooltip = L["This allows you to import appearance settings which other people have exported."], }, { type = "Button", text = L["Export Appearance Settings"], relativeWidth = 0.5, callback = ShowExportFrame, tooltip = L["This allows you to export your appearance settings to share with others."], }, { type = "HeadingLine" }, }, }, }, }, } -- extra multi-account syncing widgets for account, players in pairs(TSM.db.realm.syncAccounts) do local playerList = {} for player in pairs(players) do tinsert(playerList, player) end local widgets = { { type = "Button", text = DELETE, relativeWidth = 0.2, callback = function() TSM.db.realm.syncAccounts[account] = nil parent:ReloadTab() end, }, { type = "Label", relativeWidth = 0.79, text = table.concat(playerList, ", "), } } for _, widget in ipairs(widgets) do tinsert(page[1].children[2].children, widget) end end local function expandColor(tbl) return { tbl[1] / 255, tbl[2] / 255, tbl[3] / 255, tbl[4] } end local function compressColor(r, g, b, a) return { r * 255, g * 255, b * 255, a } end local frameColorOptions = { { L["Frame Background - Backdrop"], "frameBG", "backdrop" }, { L["Frame Background - Border"], "frameBG", "border" }, { L["Region - Backdrop"], "frame", "backdrop" }, { L["Region - Border"], "frame", "border" }, { L["Content - Backdrop"], "content", "backdrop" }, { L["Content - Border"], "content", "border" }, } for _, optionInfo in ipairs(frameColorOptions) do local label, key, subKey = unpack(optionInfo) local widget = { type = "ColorPicker", label = label, relativeWidth = 0.5, hasAlpha = true, value = expandColor(TSM.db.profile.design.frameColors[key][subKey]), callback = function(_, _, ...) TSM.db.profile.design.frameColors[key][subKey] = compressColor(...) TSMAPI:UpdateDesign() end, } tinsert(page[1].children[4].children, widget) end tinsert(page[1].children[4].children, { type = "HeadingLine" }) local textColorOptions = { { L["Icon Region"], "iconRegion", "enabled" }, { L["Title"], "title", "enabled" }, { L["Label Text - Enabled"], "label", "enabled" }, { L["Label Text - Disabled"], "label", "disabled" }, { L["Content Text - Enabled"], "text", "enabled" }, { L["Content Text - Disabled"], "text", "disabled" }, } for _, optionInfo in ipairs(textColorOptions) do local label, key, subKey = unpack(optionInfo) local widget = { type = "ColorPicker", label = label, relativeWidth = 0.5, hasAlpha = true, value = expandColor(TSM.db.profile.design.textColors[key][subKey]), callback = function(_, _, ...) TSM.db.profile.design.textColors[key][subKey] = compressColor(...) TSMAPI:UpdateDesign() end, } tinsert(page[1].children[4].children, widget) end tinsert(page[1].children[4].children, { type = "HeadingLine" }) local inlineColorOptions = { { L["Link Text (Requires Reload)"], "link" }, { L["Link Text 2 (Requires Reload)"], "link2" }, { L["Category Text (Requires Reload)"], "category" }, { L["Category Text 2 (Requires Reload)"], "category2" }, { L["Item Tooltip Text"], "tooltip" }, { L["Advanced Option Text"], "advanced" }, } for _, optionInfo in ipairs(inlineColorOptions) do local label, key = unpack(optionInfo) local widget = { type = "ColorPicker", label = label, relativeWidth = 0.5, hasAlpha = true, value = expandColor(TSM.db.profile.design.inlineColors[key]), callback = function(_, _, ...) TSM.db.profile.design.inlineColors[key] = compressColor(...) TSMAPI:UpdateDesign() end, } tinsert(page[1].children[4].children, widget) end tinsert(page[1].children[4].children, { type = "HeadingLine" }) -- Figure out which fonts to automatically select in the dropdown. -- NOTE: We visually fall back to our defaults if the stored names are -- invalid, to avoid confusion if user-fonts are temporarily unavailable. local availableFontTitlesList = LSM:List("font") local selectedContentFontIndex = -1 local selectedBoldFontIndex = -1 local arialNarrowFontIndex = 1 local tsmDroidBoldFontIndex = 1 for i,v in ipairs(availableFontTitlesList) do if v == "Arial Narrow" then arialNarrowFontIndex = i elseif v == "TSM Droid Sans Bold" then tsmDroidBoldFontIndex = i end if v == TSM.db.profile.design.fonts.content then selectedContentFontIndex = i elseif v == TSM.db.profile.design.fonts.bold then selectedBoldFontIndex = i end end if selectedContentFontIndex == -1 then selectedContentFontIndex = arialNarrowFontIndex end if selectedBoldFontIndex == -1 then selectedBoldFontIndex = tsmDroidBoldFontIndex end local miscWidgets = { { type = "Dropdown", relativeWidth = 0.5, label = L["Normal Font (Requires Reload)"], list = availableFontTitlesList, value = selectedContentFontIndex, callback = function(_, _, index) local fontTitle = availableFontTitlesList[index] TSM.db.profile.design.fonts.content = fontTitle end, tooltip = format(L["Default: \"%s\"."], "Arial Narrow"), }, { type = "Dropdown", relativeWidth = 0.5, label = L["Header Font (Requires Reload)"], list = availableFontTitlesList, value = selectedBoldFontIndex, callback = function(_, _, index) local fontTitle = availableFontTitlesList[index] TSM.db.profile.design.fonts.bold = fontTitle end, tooltip = format(L["Default: \"%s\"."], "TSM Droid Sans Bold"), }, { type = "Slider", relativeWidth = 0.5, label = L["Small Text Size (Requires Reload)"], min = 6, max = 30, step = 1, settingInfo = { TSM.db.profile.design.fontSizes, "small" }, }, { type = "Slider", relativeWidth = 0.5, label = L["Medium Text Size (Requires Reload)"], min = 6, max = 30, step = 1, settingInfo = { TSM.db.profile.design.fontSizes, "medium" }, }, { type = "Slider", relativeWidth = 0.5, label = L["Normal Text Size (Requires Reload)"], min = 6, max = 30, step = 1, settingInfo = { TSM.db.profile.design.fontSizes, "normal" }, }, { type = "Slider", relativeWidth = 0.5, label = L["Border Thickness (Requires Reload)"], min = 0, max = 3, step = .1, settingInfo = { TSM.db.profile.design, "edgeSize" }, }, } for _, widget in ipairs(miscWidgets) do tinsert(page[1].children[4].children, widget) end lib:BuildPage(parent, page) end function private:LoadProfilesPage(container) -- Popup Confirmation Window used in this module StaticPopupDialogs["TSMDeleteConfirm"] = StaticPopupDialogs["TSMDeleteConfirm"] or { text = L["Are you sure you want to delete the selected profile?"], button1 = ACCEPT, button2 = CANCEL, timeout = 0, whileDead = true, hideOnEscape = true, OnCancel = false, -- OnAccept defined later } StaticPopupDialogs["TSMCopyProfileConfirm"] = StaticPopupDialogs["TSMCopyProfileConfirm"] or { text = L["Are you sure you want to overwrite the current profile with the selected profile?"], button1 = ACCEPT, button2 = CANCEL, timeout = 0, whileDead = true, hideOnEscape = true, OnCancel = false, -- OnAccept defined later } -- profiles page local text = { default = L["Default"], intro = L["You can change the active database profile, so you can have different settings for every character."], reset_desc = L["Reset the current profile back to its default values, in case your configuration is broken, or you simply want to start over."], reset = L["Reset Profile"], choose_desc = L["You can either create a new profile by entering a name in the editbox, or choose one of the already exisiting profiles."], new = L["New"], new_sub = L["Create a new empty profile."], choose = L["Existing Profiles"], copy_desc = L["Copy the settings from one existing profile into the currently active profile."], copy = L["Copy From"], delete_desc = L["Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file."], delete = L["Delete a Profile"], profiles = L["Profiles"], current = L["Current Profile:"] .. " " .. TSMAPI.Design:ColorText(TSM.db:GetCurrentProfile(), "link"), } -- Returns a list of all the current profiles with common and nocurrent modifiers. -- This code taken from AceDBOptions-3.0.lua local function GetProfileList(db, common, nocurrent) local profiles = {} local tmpprofiles = {} local defaultProfiles = { ["Default"] = "Default" } -- copy existing profiles into the table local currentProfile = db:GetCurrentProfile() for i, v in pairs(db:GetProfiles(tmpprofiles)) do if not (nocurrent and v == currentProfile) then profiles[v] = v end end -- add our default profiles to choose from ( or rename existing profiles) for k, v in pairs(defaultProfiles) do if (common or profiles[k]) and not (nocurrent and k == currentProfile) then profiles[k] = v end end for itemString, _ in pairs(TSM.db.profile.items) do -- check if item is cached local _,_,itemID = itemString:find("item:(%d+)") if itemID then if Item then local item = Item:CreateFromID(itemID) item:Query() else TSMAPI:GetSafeItemInfo(tonumber(itemID)) end end end return profiles end local page = { { -- scroll frame to contain everything type = "ScrollFrame", layout = "Flow", children = { { type = "Label", text = text["intro"] .. "\n\n", relativeWidth = 1, }, { type = "Label", text = text["reset_desc"], relativeWidth = 1, }, { type = "Button", text = text["reset"], relativeWidth = .5, callback = function() TSM.db:ResetProfile() end, }, { type = "Label", text = text["current"], relativeWidth = .49, }, { type = "HeadingLine", }, { type = "Label", text = text["choose_desc"], relativeWidth = 1, }, { type = "EditBox", label = text["new"], value = "", relativeWidth = .5, callback = function(_, _, value) value = value:trim() if value == "" then return TSM:Print(L["You cannot create a profile with an empty name."]) end TSM.db:SetProfile(value) container:ReloadTab() end, }, { type = "Dropdown", label = text["choose"], list = GetProfileList(TSM.db, true, nil), value = TSM.db:GetCurrentProfile(), relativeWidth = .49, callback = function(_, _, value) if value ~= TSM.db:GetCurrentProfile() then TSM.db:SetProfile(value) container:ReloadTab() end end, }, { type = "HeadingLine", }, { type = "Label", text = text["copy_desc"], relativeWidth = 1, }, { type = "Dropdown", label = text["copy"], list = GetProfileList(TSM.db, true, nil), value = "", disabled = not GetProfileList(TSM.db, true, nil) and true, callback = function(_, _, value) if value == TSM.db:GetCurrentProfile() then return end StaticPopupDialogs["TSMCopyProfileConfirm"].OnAccept = function() TSM.db:CopyProfile(value) container:ReloadTab() end TSMAPI:ShowStaticPopupDialog("TSMCopyProfileConfirm") end, }, { type = "HeadingLine", }, { type = "Label", text = text["delete_desc"], relativeWidth = 1, }, { type = "Dropdown", label = text["delete"], list = GetProfileList(TSM.db, true, nil), value = "", disabled = not GetProfileList(TSM.db, true, nil) and true, callback = function(_, _, value) if TSM.db:GetCurrentProfile() == value then TSM:Print(L["Cannot delete currently active profile!"]) return end StaticPopupDialogs["TSMDeleteConfirm"].OnAccept = function() TSM.db:DeleteProfile(value) container:ReloadTab() end TSMAPI:ShowStaticPopupDialog("TSMDeleteConfirm") end, }, }, }, } TSMAPI:BuildPage(container, page) end local treeGroup function private:LoadCustomPriceSources(parent) private.treeGroup = AceGUI:Create("TSMTreeGroup") private.treeGroup:SetLayout("Fill") private.treeGroup:SetCallback("OnGroupSelected", private.SelectTree) private.treeGroup:SetStatusTable(TSM.db.profile.customPriceSourceTreeStatus) parent:AddChild(private.treeGroup) private:UpdateTree() private.treeGroup:SelectByPath(1) end function private:UpdateTree() if not private.treeGroup then return end local children = {} for name in pairs(TSM.db.global.customPriceSources) do tinsert(children, {value=name, text=name}) end sort(children, function(a, b) return strlower(a.value) < strlower(b.value) end) private.treeGroup:SetTree({{value=1, text=L["Sources"], children=children}}) end function private.SelectTree(treeGroup, _, selection) treeGroup:ReleaseChildren() selection = {("\001"):split(selection)} if #selection == 1 then private:DrawNewCustomPriceSource(treeGroup) else local name = selection[#selection] private:DrawCustomPriceSourceOptions(treeGroup, name) end end function private:DrawNewCustomPriceSource(container) local page = { { -- scroll frame to contain everything type = "ScrollFrame", layout = "List", children = { { type = "InlineGroup", layout = "flow", title = L["New Custom Price Source"], children = { { type = "Label", relativeWidth = 1, text = L["Custom price sources allow you to create more advanced custom prices throughout all of the TSM modules. Just as you can use the built-in price sources such as 'vendorsell' and 'vendorbuy' in your custom prices, you can use ones you make here (which themselves are custom prices)."], }, { type = "HeadingLine", }, { type = "EditBox", label = L["Custom Price Source Name"], relativeWidth = 0.8, callback = function(self,_,value) value = strlower((value or ""):trim()) if value == "" then return end if gsub(value, "([a-z]+)", "") ~= "" then return TSM:Print(L["The name can ONLY contain letters. No spaces, numbers, or special characters."]) end if TSM.db.global.customPriceSources[value] then return TSM:Printf(L["Error creating custom price source. Custom price source with name '%s' already exists."], value) end TSM.db.global.customPriceSources[value] = "" private:UpdateTree() if TSM.db.profile.gotoNewCustomPriceSource then private.treeGroup:SelectByPath(1, value) else self:SetText() self:SetFocus() end end, tooltip = L["Give your new custom price source a name. This is what you will type in to custom prices and is case insensitive (everything will be saved as lower case)."].."\n\n"..TSMAPI.Design:ColorText(L["The name can ONLY contain letters. No spaces, numbers, or special characters."], "link"), }, { type = "CheckBox", label = L["Switch to New Custom Price Source After Creation"], relativeWidth = 1, settingInfo = {TSM.db.profile, "gotoNewCustomPriceSource"}, }, }, }, }, }, } TSMAPI:BuildPage(container, page) end function private:DrawCustomPriceSourceOptions(container, customPriceName) local page = { { -- scroll frame to contain everything type = "ScrollFrame", layout = "List", children = { { type = "InlineGroup", layout = "flow", title = L["Custom Price Source"], children = { { type = "Label", relativeWidth = 1, text = L["Below, set the custom price that will be evaluated for this custom price source."], }, { type = "HeadingLine", }, { type = "EditBox", label = L["Custom Price for this Source"], settingInfo = {TSM.db.global.customPriceSources, customPriceName}, relativeWidth = 0.49, acceptCustom = true, tooltip = "", }, }, }, { type = "InlineGroup", layout = "flow", title = L["Management"], children = { { type = "EditBox", label = L["Rename Custom Price Source"], value = operationName, relativeWidth = 0.5, callback = function(self,_,name) name = strlower((name or ""):trim()) if name == "" then return end if gsub(name, "([a-z]+)", "") ~= "" then return TSM:Print(L["The name can ONLY contain letters. No spaces, numbers, or special characters."]) end if TSM.db.global.customPriceSources[name] then return TSM:Printf(L["Error renaming custom price source. Custom price source with name '%s' already exists."], name) end TSM.db.global.customPriceSources[name] = TSM.db.global.customPriceSources[customPriceName] TSM.db.global.customPriceSources[customPriceName] = nil private:UpdateTree() private.treeGroup:SelectByPath(1, name) end, tooltip = L["Give your new custom price source a name. This is what you will type in to custom prices and is case insensitive (everything will be saved as lower case)."].."\n\n"..TSMAPI.Design:ColorText(L["The name can ONLY contain letters. No spaces, numbers, or special characters."], "link"), }, { type = "Button", text = L["Delete Custom Price Source"], relativeWidth = 0.5, callback = function() TSM.db.global.customPriceSources[customPriceName] = nil private:UpdateTree() private.treeGroup:SelectByPath(1) TSM:Printf(L["Removed '%s' as a custom price source. Be sure to update any custom prices that were using this source."], customPriceName) end, }, }, }, }, }, } TSMAPI:BuildPage(container, page) end function TSM:LoadOptions(parent) local tg = AceGUI:Create("TSMTabGroup") tg:SetLayout("Fill") tg:SetFullWidth(true) tg:SetFullHeight(true) tg:SetTabs({ { value = 1, text = L["TSM Info / Help"] }, { value = 2, text = L["Options"] }, { value = 3, text = L["Profiles"] }, { value = 4, text = TSMAPI.Design:ColorText(L["Custom Price Sources"], "advanced") } }) tg:SetCallback("OnGroupSelected", function(self, _, value) tg:ReleaseChildren() StaticPopup_Hide("TSM_GLOBAL_OPERATIONS") if value == 1 then private:LoadHelpPage(self) elseif value == 2 then private:LoadOptionsPage(self) elseif value == 3 then private:LoadProfilesPage(self) elseif value == 4 then private:LoadCustomPriceSources(self) end end) parent:AddChild(tg) tg:SelectTab(1) end