288 lines
9.1 KiB
Lua
288 lines
9.1 KiB
Lua
|
-- ------------------------------------------------------------------------------ --
|
||
|
-- TradeSkillMaster --
|
||
|
-- https://tradeskillmaster.com --
|
||
|
-- All Rights Reserved - Detailed license information included with addon. --
|
||
|
-- ------------------------------------------------------------------------------ --
|
||
|
|
||
|
local _, TSM = ...
|
||
|
local Settings = TSM.MainUI:NewPackage("Settings")
|
||
|
local L = TSM.Include("Locale").GetTable()
|
||
|
local Wow = TSM.Include("Util.Wow")
|
||
|
local UIElements = TSM.Include("UI.UIElements")
|
||
|
local private = {
|
||
|
settingPages = {
|
||
|
top = {},
|
||
|
middle = {},
|
||
|
bottom = {},
|
||
|
},
|
||
|
callback = {},
|
||
|
childSettingsPages = {},
|
||
|
sectionCollapsed = {},
|
||
|
}
|
||
|
local SECTIONS = { "top", "middle" }
|
||
|
local SETTING_PATH_SEP = "`"
|
||
|
local SETTING_LABEL_WIDTH = 400
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- Module Functions
|
||
|
-- ============================================================================
|
||
|
|
||
|
function Settings.OnInitialize()
|
||
|
TSM.MainUI.RegisterTopLevelPage(L["Settings"], private.GetSettingsFrame)
|
||
|
end
|
||
|
|
||
|
function Settings.RegisterSettingPage(name, section, callback)
|
||
|
assert(tContains(SECTIONS, section))
|
||
|
tinsert(private.settingPages[section], name)
|
||
|
private.callback[name] = callback
|
||
|
end
|
||
|
|
||
|
function Settings.RegisterChildSettingPage(parentName, childName, callback)
|
||
|
local path = parentName..SETTING_PATH_SEP..childName
|
||
|
private.childSettingsPages[parentName] = private.childSettingsPages[parentName] or {}
|
||
|
tinsert(private.childSettingsPages[parentName], childName)
|
||
|
private.callback[path] = callback
|
||
|
end
|
||
|
|
||
|
function Settings.CreateSettingLine(id, labelText, width)
|
||
|
width = width or SETTING_LABEL_WIDTH
|
||
|
|
||
|
return UIElements.New("Frame", id)
|
||
|
:SetLayout("HORIZONTAL")
|
||
|
:SetHeight(26)
|
||
|
:SetMargin(0, 0, 0, 16)
|
||
|
:AddChild(UIElements.New("Text", "label")
|
||
|
:SetWidth(width)
|
||
|
:SetFont("BODY_BODY2_MEDIUM")
|
||
|
:SetTextColor("TEXT_ALT")
|
||
|
:SetText(labelText)
|
||
|
)
|
||
|
end
|
||
|
|
||
|
function Settings.CreateHeading(id, text)
|
||
|
return UIElements.New("Text", id)
|
||
|
:SetHeight(19)
|
||
|
:SetMargin(0, 0, 0, 4)
|
||
|
:SetFont("BODY_BODY1_BOLD")
|
||
|
:SetText(text)
|
||
|
end
|
||
|
|
||
|
function Settings.CreateInputWithReset(id, label, context, validate)
|
||
|
local scope, namespace, key = strsplit(".", context)
|
||
|
local validateFunc, validateContext = nil, nil
|
||
|
if type(validate) == "table" then
|
||
|
validateFunc = "CUSTOM_PRICE"
|
||
|
validateContext = validate
|
||
|
elseif type(validate) == "function" then
|
||
|
validateFunc = validate
|
||
|
elseif validate == nil then
|
||
|
validateFunc = "CUSTOM_PRICE"
|
||
|
else
|
||
|
error("Invalid validate: "..tostring(validate))
|
||
|
end
|
||
|
return UIElements.New("Frame", id)
|
||
|
:SetLayout("VERTICAL")
|
||
|
:AddChild(UIElements.New("Text", "label")
|
||
|
:SetHeight(18)
|
||
|
:SetMargin(0, 0, 0, 4)
|
||
|
:SetFont("BODY_BODY2_MEDIUM")
|
||
|
:SetTextColor("TEXT_ALT")
|
||
|
:SetText(label)
|
||
|
)
|
||
|
:AddChild(UIElements.New("Frame", "content")
|
||
|
:SetLayout("HORIZONTAL")
|
||
|
:SetHeight(24)
|
||
|
:AddChild(UIElements.New("Input", "input")
|
||
|
:SetMargin(0, 8, 0, 0)
|
||
|
:SetBackgroundColor("ACTIVE_BG")
|
||
|
:SetValidateFunc(validateFunc, validateContext)
|
||
|
:SetSettingInfo(TSM.db[scope][namespace], key)
|
||
|
:SetScript("OnValueChanged", private.InputOnValueChanged)
|
||
|
)
|
||
|
:AddChild(UIElements.New("ActionButton", "resetButton")
|
||
|
:SetWidth(108)
|
||
|
:SetText(L["Reset"])
|
||
|
:SetDisabled(TSM.db[scope][namespace][key] == TSM.db:GetDefault(scope, namespace, key))
|
||
|
:SetScript("OnClick", private.ResetBtnOnClick)
|
||
|
:SetContext(context)
|
||
|
)
|
||
|
)
|
||
|
end
|
||
|
|
||
|
function Settings.CreateExpandableSection(pageName, id, text, description, descriptionHeight)
|
||
|
return UIElements.New("CollapsibleContainer", id)
|
||
|
:SetLayout("VERTICAL")
|
||
|
:SetMargin(0, 0, 0, 8)
|
||
|
:SetContextTable(private.sectionCollapsed, pageName..text)
|
||
|
:SetHeadingText(text)
|
||
|
:AddChild(UIElements.New("Text", "description")
|
||
|
:SetHeight(descriptionHeight or 20)
|
||
|
:SetMargin(0, 0, 0, 12)
|
||
|
:SetFont("BODY_BODY3")
|
||
|
:SetText(description)
|
||
|
)
|
||
|
end
|
||
|
|
||
|
function Settings.PromptToReload()
|
||
|
StaticPopupDialogs["TSMReloadPrompt"] = StaticPopupDialogs["TSMReloadPrompt"] or {
|
||
|
text = L["You must reload your UI for these settings to take effect. Reload now?"],
|
||
|
button1 = YES,
|
||
|
button2 = NO,
|
||
|
timeout = 0,
|
||
|
OnAccept = ReloadUI,
|
||
|
}
|
||
|
Wow.ShowStaticPopupDialog("TSMReloadPrompt")
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- Settings UI
|
||
|
-- ============================================================================
|
||
|
|
||
|
function private.GetSettingsFrame()
|
||
|
TSM.UI.AnalyticsRecordPathChange("main", "settings")
|
||
|
local defaultPage = private.settingPages.top[1]
|
||
|
|
||
|
local frame = UIElements.New("Frame", "settings")
|
||
|
:SetLayout("HORIZONTAL")
|
||
|
:SetBackgroundColor("PRIMARY_BG_ALT")
|
||
|
:AddChild(UIElements.New("Frame", "settingNavigation")
|
||
|
:SetLayout("VERTICAL")
|
||
|
:SetWidth(160)
|
||
|
:SetPadding(12, 12, 1, 9)
|
||
|
:AddChild(UIElements.New("Frame", "top")
|
||
|
:SetLayout("VERTICAL")
|
||
|
)
|
||
|
:AddChild(UIElements.New("Texture", "vline")
|
||
|
:SetHeight(1)
|
||
|
:SetMargin(0, 0, 8, 8)
|
||
|
:SetTexture("ACTIVE_BG_ALT")
|
||
|
)
|
||
|
:AddChild(UIElements.New("Frame", "middle")
|
||
|
:SetLayout("VERTICAL")
|
||
|
)
|
||
|
:AddChild(UIElements.New("Spacer", "spacer")
|
||
|
-- make all the navigation align to the top
|
||
|
)
|
||
|
)
|
||
|
:AddChild(UIElements.New("Texture", "divider")
|
||
|
:SetWidth(2)
|
||
|
:SetTexture("ACTIVE_BG")
|
||
|
)
|
||
|
:AddChild(UIElements.New("Frame", "contentFrame")
|
||
|
:SetLayout("VERTICAL")
|
||
|
:SetBackgroundColor("PRIMARY_BG")
|
||
|
:AddChild(UIElements.New("ViewContainer", "content")
|
||
|
:SetNavCallback(private.ContentNavCallback)
|
||
|
)
|
||
|
)
|
||
|
|
||
|
local content = frame:GetElement("contentFrame.content")
|
||
|
local settingNav = frame:GetElement("settingNavigation")
|
||
|
for _, location in ipairs(SECTIONS) do
|
||
|
local navFrame = settingNav:GetElement(location)
|
||
|
for _, settingName in ipairs(private.settingPages[location]) do
|
||
|
navFrame:AddChild(UIElements.New("Button", settingName)
|
||
|
:SetHeight(20)
|
||
|
:SetMargin(0, 0, 8, 0)
|
||
|
:SetFont("BODY_BODY2_BOLD")
|
||
|
:SetJustifyH("LEFT")
|
||
|
:SetContext(settingName)
|
||
|
:SetText(settingName)
|
||
|
:SetScript("OnClick", private.NavButtonOnClick)
|
||
|
)
|
||
|
content:AddPath(settingName, settingName == defaultPage)
|
||
|
if private.childSettingsPages[settingName] then
|
||
|
for _, childSettingName in ipairs(private.childSettingsPages[settingName]) do
|
||
|
local path = settingName..SETTING_PATH_SEP..childSettingName
|
||
|
navFrame:AddChild(UIElements.New("Button", path)
|
||
|
:SetHeight(20)
|
||
|
:SetMargin(9, 0, 8, 0)
|
||
|
:SetFont("BODY_BODY3_MEDIUM")
|
||
|
:SetJustifyH("LEFT")
|
||
|
:SetContext(path)
|
||
|
:SetText(strupper(childSettingName))
|
||
|
:SetScript("OnClick", private.NavButtonOnClick)
|
||
|
)
|
||
|
content:AddPath(path, path == defaultPage)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
private.UpdateNavFrame(settingNav, defaultPage)
|
||
|
return frame
|
||
|
end
|
||
|
|
||
|
function private.ContentNavCallback(content, path)
|
||
|
return private.callback[path]()
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- Local Script Handlers
|
||
|
-- ============================================================================
|
||
|
|
||
|
function private.NavButtonOnClick(button)
|
||
|
local path = button:GetContext()
|
||
|
if private.childSettingsPages[path] then
|
||
|
-- select the first child
|
||
|
path = path..SETTING_PATH_SEP..private.childSettingsPages[path][1]
|
||
|
end
|
||
|
|
||
|
local contentFrame = button:GetElement("__parent.__parent.__parent.contentFrame")
|
||
|
local navFrame = contentFrame:GetElement("__parent.settingNavigation")
|
||
|
private.UpdateNavFrame(navFrame, path)
|
||
|
navFrame:Draw()
|
||
|
contentFrame:GetElement("content"):SetPath(path, true)
|
||
|
end
|
||
|
|
||
|
function private.InputOnValueChanged(input)
|
||
|
local button = input:GetElement("__parent.resetButton")
|
||
|
local scope, namespace, key = strsplit(".", button:GetContext())
|
||
|
button:SetDisabled(TSM.db[scope][namespace][key] == TSM.db:GetDefault(scope, namespace, key))
|
||
|
:Draw()
|
||
|
end
|
||
|
|
||
|
function private.ResetBtnOnClick(button)
|
||
|
local scope, namespace, key = strsplit(".", button:GetContext())
|
||
|
local defaultValue = TSM.db:GetDefault(scope, namespace, key)
|
||
|
TSM.db:Set(scope, nil, namespace, key, defaultValue)
|
||
|
button:GetElement("__parent.input")
|
||
|
:SetValue(defaultValue)
|
||
|
:Draw()
|
||
|
button:SetDisabled(true)
|
||
|
:Draw()
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- Private Helper Functions
|
||
|
-- ============================================================================
|
||
|
|
||
|
function private.UpdateNavFrame(navFrame, selectedPath)
|
||
|
local selectedSetting = strsplit(SETTING_PATH_SEP, selectedPath)
|
||
|
for _, location in ipairs(SECTIONS) do
|
||
|
for _, settingName in ipairs(private.settingPages[location]) do
|
||
|
navFrame:GetElement(location ..".".. settingName)
|
||
|
:SetTextColor(settingName == selectedSetting and "TEXT" or "ACTIVE_BG_ALT")
|
||
|
if private.childSettingsPages[settingName] then
|
||
|
for _, childSettingName in ipairs(private.childSettingsPages[settingName]) do
|
||
|
local path = settingName..SETTING_PATH_SEP..childSettingName
|
||
|
if settingName == selectedSetting then
|
||
|
navFrame:GetElement(location ..".".. path)
|
||
|
:SetTextColor(path == selectedPath and "INDICATOR" or "TEXT")
|
||
|
:Show()
|
||
|
else
|
||
|
navFrame:GetElement(location ..".".. path):Hide()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|