WoWInterface SVN PocketPlot

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /branches
    from Rev 22 to Rev 23
    Reverse comparison

Rev 22 → Rev 23

PocketPlot/media Property changes : Added: svn:ignore + PPblips2.png PPblips.png
PocketPlot/libs/LibStub.lua New file
0,0 → 1,30
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local LibStub = _G[LIBSTUB_MAJOR]
 
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
 
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
 
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
 
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
 
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
PocketPlot/libs/LibSimpleOptions-1.0.lua New file
0,0 → 1,955
--[[
Name: LibSimpleOptions-1.0
Revision: $Rev: 39 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Description: A library to provide a way to easily create controls for Blizzard's options system
License: MIT
]]
 
local MAJOR_VERSION = "LibSimpleOptions-1.0"
local MINOR_VERSION = 90000 + tonumber(("$Revision: 39 $"):match("(%d+)"))
 
if not LibStub then error(MAJOR_VERSION .. " requires LibStub") end
 
-- #AUTODOC_NAMESPACE LibSimpleOptions
 
local LibSimpleOptions, oldLib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
if not LibSimpleOptions then
return
end
if oldLib then
oldLib = {}
for k, v in pairs(LibSimpleOptions) do
LibSimpleOptions[k] = nil
oldLib[k] = v
end
end
 
local getArgs, doneArgs
do
local tmp = {}
function getArgs(...)
assert(next(tmp) == nil)
for i = 1, select('#', ...), 2 do
local k, v = select(i, ...)
if type(k) ~= "string" then
error(("Received a bad key, must be a %q, got %q (%s)"):format("string", type(k), tostring(k)), 3)
elseif tmp[k] ~= nil then
error(("Received key %q twice"):format(k), 3)
end
tmp[k] = v
end
return tmp
end
function doneArgs(args)
assert(args == tmp)
for k in pairs(args) do
args[k] = nil
end
return nil
end
end
 
local WotLK = not not ToggleAchievementFrame
 
local panels
if oldLib then
panels = oldLib.panels or {}
else
panels = {}
end
LibSimpleOptions.panels = panels
 
local panelMeta
if oldLib then
panelMeta = oldLib.panelMeta or {}
else
panelMeta = {}
end
LibSimpleOptions.panelMeta = panelMeta
for funcName in pairs(panelMeta) do
for panel in pairs(panels) do
panel[funcName] = nil
end
panelMeta[funcName] = nil
end
 
do
local function update(control, ...)
if (...) ~= control.value then
control:SetValue(...)
end
end
--- Refresh a panel's controls
-- This updates any controls that provide a getFunc
-- When a panel is shown, this is automatically called
-- @name panel:Refresh
-- @usage panel:Refresh()
function panelMeta:Refresh()
for control in pairs(self.controls) do
if control.getFunc then
update(control, control.getFunc())
end
end
if self.refreshFunc then
self:refreshFunc()
end
end
local function panel_OnShow(self)
self:SetScript("OnShow", self.Refresh)
self:controlCreationFunc()
self.controlCreationFunc = nil
self:Refresh()
end
local function panel_okay(self)
for control in pairs(self.controls) do
control.oldValue = control.value
if control.okayFunc then
control.okayFunc()
end
end
end
local function panel_cancel(self)
for control in pairs(self.controls) do
control:SetValue(control.oldValue)
if control.cancelFunc then
control.cancelFunc()
end
end
end
local function panel_default(self)
for control in pairs(self.controls) do
control:SetValue(control.default)
if control.defaultFunc then
control.defaultFunc()
end
end
end
local function makePanel(name, parentName, controlCreationFunc)
local panel
if not parentName then
panel = CreateFrame("Frame", name .. "_Panel")
else
panel = CreateFrame("Frame", parentName .. "_Panel_" .. name)
end
panels[panel] = true
 
panel.name = name
panel.controls = {}
panel.parent = parentName
 
panel.okay = panel_okay
panel.cancel = panel_cancel
panel.default = panel_default
 
InterfaceOptions_AddCategory(panel)
 
panel.controlCreationFunc = controlCreationFunc
panel:SetScript("OnShow", panel_OnShow)
for k, v in pairs(panelMeta) do
panel[k] = v
end
end
 
--- Make a new options panel and add it to the Blizzard Interface Options
-- @param name name of your panel
-- @param controlCreationFunc function to call when the panel is first shown
-- @usage LibStub("LibSimpleOptions-1.0").AddOptionsPanel("My Options", function(panel) ... end)
-- @return the created panel
function LibSimpleOptions.AddOptionsPanel(name, controlCreationFunc)
return makePanel(name, nil, controlCreationFunc)
end
 
--- Make a new options panel that is a child of another options panel and add it to the Blizzard Interface Options
-- @param parentName name of the parent panel
-- @param name name of your panel
-- @param controlCreationFunc function to call when the panel is first shown
-- @usage LibStub("LibSimpleOptions-1.0").AddOptionsPanel("My Options", "My Suboptions", function(panel) ... end)
-- @return the created panel
function LibSimpleOptions.AddSuboptionsPanel(parentName, name, controlCreationFunc)
return makePanel(name, parentName, controlCreationFunc)
end
end
 
--- Return a new title text and sub-text for a panel.
-- Note that this automatically places the title and sub-text appropriately
-- @name panel:MakeTitleTextAndSubText
-- @param titleText the text to show as the title
-- @param subTextText the text to show as the sub-text
-- @usage local title, subText = panel:MakeTitleTextAndSubText("My Options", "These allow you to change assorted options")
-- @return the title FontString
-- @return the sub-text FontString
function panelMeta:MakeTitleTextAndSubText(titleText, subTextText)
local title = self:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
title:SetText(titleText)
title:SetJustifyH("LEFT")
title:SetJustifyV("TOP")
title:SetPoint("TOPLEFT", 16, -16)
 
local subText = self:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
subText:SetText(subTextText)
subText:SetNonSpaceWrap(true)
subText:SetJustifyH("LEFT")
subText:SetJustifyV("TOP")
subText:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
subText:SetPoint("RIGHT", -32, 0)
 
return title, subText
end
 
do
local backdrop = {
bgFile = [=[Interface\Buttons\WHITE8X8]=],
edgeFile = [=[Interface\Tooltips\UI-Tooltip-Border]=],
tile = true,
tileSize = 16,
edgeSize = 16,
insets = { left = 3, right = 3, top = 3, bottom = 3 },
}
--- Return a scrollable frame to organize controls within
-- This is useful to create if you have too many controls to properly fit within one panel
-- @name panel:MakeScrollFrame
-- @usage local scrollFrame = panel:MakeScrollFrame()
-- @return the ScrollFrame
function panelMeta:MakeScrollFrame()
local name
local i = 0
repeat
i = i + 1
name = self:GetName() .. "_ScrollFrame" .. i
until not _G[name]
local scrollFrame = CreateFrame("ScrollFrame", name, self, "UIPanelScrollFrameTemplate")
scrollFrame:SetFrameLevel(scrollFrame:GetFrameLevel() + 1)
local bg = CreateFrame("Frame", nil, self)
bg:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", -3, 3)
bg:SetPoint("BOTTOMRIGHT", scrollFrame, "BOTTOMRIGHT", 3, -3)
bg:SetBackdrop(backdrop)
bg:SetBackdropColor(0, 0, 0, 0.25)
local scrollChild = CreateFrame("Frame", name .. "_Child", scrollFrame)
scrollFrame:SetScrollChild(scrollChild)
scrollChild:SetWidth(1)
scrollChild:SetHeight(1)
return scrollFrame, scrollChild
end
end
 
do
local function slider_OnValueChanged(self)
self.value = self:GetValue()
self:SetValue(self:GetValue())
end
 
local function slider_SetValue(self, value)
getmetatable(self).__index.SetValue(self, value)
self.value = value
self.changeFunc(value)
if self.currentText then
self.currentText:SetText(self.currentTextFunc(value))
end
end
 
--- Return a horizontal slider
-- This is primarily for manipulating numbers within a range
-- @name panel:MakeSlider
-- @param ... tuple of key-value pairs<br/>
-- name: What the slider displays above it<br/>
-- description: What the tooltip displays when hovering over<br/>
-- minText: What the slider shows on the left side<br/>
-- maxText: What the slider shows on the right side<br/>
-- minValue: The minimum value of the slider<br/>
-- maxValue: The maximum value of the slider<br/>
-- [optional] step: The amount that the slider steps between movements<br/>
-- default: The default value<br/>
-- current: The current value - can provide either this or getFunc<br/>
-- getFunc: Function to get the current value<br/>
-- setFunc: What is called when the value changes<br/>
-- [optional] currentTextFunc: What is called to get text value at the bottom<br/>
-- [optional] okayFunc: Called when the okay button is pressed<br/>
-- [optional] cancelFunc: Called when the cancel button is pressed<br/>
-- [optional] defaultFunc: Called when the default button is pressed
-- @usage panel:MakeSlider(
-- 'name', 'Range',
-- 'description', 'Specify your tooltip description',
-- 'minText', '0%',
-- 'maxText', '100%',
-- 'minValue', 0,
-- 'maxValue', 1,
-- 'step', 0.05,
-- 'default', 0.5,
-- 'current', db.currentRange,
-- 'setFunc', function(value) db.currentRange = value end,
-- 'currentTextFunc', function(value) return ("%.0f%%"):format(value * 100) end
-- )
-- @return the Slider
function panelMeta:MakeSlider(...)
local args = getArgs(...)
if type(args.name) ~= "string" then
error(("name must be %q, got %q (%s)"):format("string", type(args.name), tostring(args.name)), 2)
elseif type(args.description) ~= "string" then
error(("description must be %q, got %q (%s)"):format("string", type(args.description), tostring(args.description)), 2)
elseif type(args.minText) ~= "string" then
error(("minText must be %q, got %q (%s)"):format("string", type(args.minText), tostring(args.minText)), 2)
elseif type(args.maxText) ~= "string" then
error(("maxText must be %q, got %q (%s)"):format("string", type(args.maxText), tostring(args.maxText)), 2)
elseif type(args.minValue) ~= "number" then
error(("minValue must be %q, got %q (%s)"):format("number", type(args.minValue), tostring(args.minValue)), 2)
elseif type(args.maxValue) ~= "number" then
error(("maxValue must be %q, got %q (%s)"):format("number", type(args.maxValue), tostring(args.maxValue)), 2)
elseif args.step and type(args.step) ~= "number" then
error(("step must be %q or %q, got %q (%s)"):format("nil", "number", type(args.step), tostring(args.step)), 2)
elseif type(args.default) ~= "number" then
error(("default must be %q, got %q (%s)"):format("number", type(args.default), tostring(args.default)), 2)
elseif args.default < args.minValue or args.default > args.maxValue then
error(("default must be [%s, %s], got %s"):format(args.minValue, args.maxValue, tostring(args.default)), 2)
elseif not args.current == not args.getFunc then
error(("either current or getFunc must be supplied, but not both"), 2)
elseif args.current and type(args.current) ~= "number" then
error(("current must be %q, got %q (%s)"):format("number", type(args.current), tostring(args.current)), 2)
elseif args.getFunc and type(args.getFunc) ~= "function" then
error(("getFunc must be %q, got %q (%s)"):format("function", type(args.getFunc), tostring(args.getFunc)), 2)
elseif type(args.setFunc) ~= "function" then
error(("setFunc must be %q, got %q (%s)"):format("function", type(args.setFunc), tostring(args.setFunc)), 2)
elseif args.currentTextFunc and type(args.currentTextFunc) ~= "function" then
error(("currentTextFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.currentTextFunc), tostring(args.currentTextFunc)), 2)
elseif args.okayFunc and type(args.okayFunc) ~= "function" then
error(("okayFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.okayFunc), tostring(args.okayFunc)), 2)
elseif args.cancelFunc and type(args.cancelFunc) ~= "function" then
error(("cancelFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.cancelFunc), tostring(args.cancelFunc)), 2)
elseif args.defaultFunc and type(args.defaultFunc) ~= "function" then
error(("defaultFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.defaultFunc), tostring(args.defaultFunc)), 2)
end
 
local name
local i = 0
repeat
i = i + 1
name = self:GetName() .. "_Slider" .. i
until not _G[name]
local slider = CreateFrame("Slider", name, self, "OptionsSliderTemplate")
self.controls[slider] = true
_G[slider:GetName() .. "Text"]:SetText(args.name)
slider.tooltipText = args.description
_G[slider:GetName() .. "Text"]:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
_G[slider:GetName() .. "Low"]:SetText(args.minText)
_G[slider:GetName() .. "Low"]:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
_G[slider:GetName() .. "High"]:SetText(args.maxText)
_G[slider:GetName() .. "High"]:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
 
local current
if args.getFunc then
slider.getFunc = args.getFunc
current = args.getFunc()
else
current = args.current
end
 
if args.currentTextFunc then
slider.currentTextFunc = args.currentTextFunc
local currentText = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
slider.currentText = currentText
currentText:SetPoint("TOP", slider, "CENTER", 0, -8)
currentText:SetText(args.currentTextFunc(current))
end
 
slider.default = args.default
slider:SetMinMaxValues(args.minValue, args.maxValue)
if args.step then
slider:SetValueStep(args.step)
end
slider.oldValue = current
slider.value = current
slider:SetValue(current)
slider.changeFunc = args.setFunc
slider.SetValue = slider_SetValue
slider:SetScript("OnValueChanged", slider_OnValueChanged)
slider.okayFunc = args.okayFunc
slider.cancelFunc = args.cancelFunc
slider.defaultFunc = args.defaultFunc
args = doneArgs(args)
return slider
end
end
 
local function generic_OnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_TOPRIGHT")
GameTooltip:SetText(self.tooltipText, nil, nil, nil, nil, 1)
end
local function generic_OnLeave(self)
GameTooltip:Hide()
end
 
do
local function dropDown_SetValue(self, value)
self.value = value
UIDropDownMenu_SetSelectedValue(self, value)
self.changeFunc(value)
end
local helper__num, helper__values
local function helper()
local value, text = helper__values[helper__num], helper__values[helper__num+1]
if value == nil then
helper__num, helper__values = nil, nil
return nil
end
helper__num = helper__num + 2
return value, text
end
local function get_iter(values)
if type(values) == "function" then
return values
end
helper__num = 1
helper__values = values
return helper
end
local SetValue_wrapper
if WotLK then
function SetValue_wrapper(self, ...)
return dropDown_SetValue(...)
end
else
SetValue_wrapper = dropDown_SetValue
end
local function dropDown_menu(self)
for value, text in get_iter(self.values) do
local info = UIDropDownMenu_CreateInfo()
info.text = text
info.value = value
info.checked = self.value == value
info.func = SetValue_wrapper
info.arg1 = self
info.arg2 = value
UIDropDownMenu_AddButton(info)
end
end
 
local tmp = {}
--- Return a single-choice dropdown menu
-- This is for choosing a single choice among many
-- @name panel:MakeDropDown
-- @param ... tuple of key-value pairs<br/>
-- name: What shows above the dropdown<br/>
-- description: What shows when hovering over the dropdown<br/>
-- values: A list of options, in order, where the odd keys are the key and even are its corresponding value<br/>
-- default: The default key<br/>
-- current: The current key - you can either provide this or getFunc<br/>
-- getFunc: Function to return the current key<br/>
-- setFunc: What is called when the key changes<br/>
-- [optional] okayFunc: Called when the okay button is pressed<br/>
-- [optional] cancelFunc: Called when the cancel button is pressed<br/>
-- [optional] defaultFunc: Called when the default button is pressed
-- @usage panel:MakeDropDown(
-- 'name', 'Choose',
-- 'description', 'Specify your tooltip description',
-- 'values', {
-- 'ONE', "One",
-- 'TWO', "Two",
-- 'THREE', "Three",
-- },
-- 'default', 'ONE',
-- 'current', db.choice,
-- 'setFunc', function(value) db.choice = value end,
-- )
-- @return the DropDown frame
function panelMeta:MakeDropDown(...)
local args = getArgs(...)
if type(args.name) ~= "string" then
error(("name must be %q, got %q (%s)"):format("string", type(args.name), tostring(args.name)), 2)
elseif type(args.description) ~= "string" then
error(("description must be %q, got %q (%s)"):format("string", type(args.description), tostring(args.description)), 2)
elseif type(args.values) ~= "function" then
if type(args.values) ~= "table" then
error(("values must be %q, got %q (%s)"):format("table", type(args.values), tostring(args.values)), 2)
elseif #args.values%2 ~= 0 then
error(("values must have an even number of items, got %d"):format(#args.values), 2)
end
for i = 1, #args.values, 2 do
local k, v = args.values[i], args.values[2]
if type(k) ~= "string" and type(k) ~= "number" then
error(("values' keys must be %q or %q, got %q (%s)"):format("string", "number", type(k), tostring(k)))
elseif type(v) ~= "string" then
error(("values' values must be %q, got %q (%s)"):format("string", type(v), tostring(v)))
end
tmp[k] = v
end
end
if type(args.default) ~= "number" and type(args.default) ~= "string" then
error(("default must be %q or %q, got %q (%s)"):format("number", "string", type(args.default), tostring(args.default)), 2)
elseif type(args.values) ~= "function" and not tmp[args.default] then
error(("default must be in values, %s is not"):format(tostring(args.default)), 2)
elseif not args.current == not args.getFunc then
error(("either current or getFunc must be supplied, but not both"), 2)
elseif args.current and type(args.current) ~= "string" and type(args.current) ~= "number" then
error(("current must be %q or %q, got %q (%s)"):format("string", "number", type(args.current), tostring(args.current)), 2)
elseif type(args.values) ~= "function" and args.current and not tmp[args.current] then
error(("current must be in values, %s is not"):format(tostring(args.current)), 2)
elseif args.getFunc and type(args.getFunc) ~= "function" then
error(("getFunc must be %q, got %q (%s)"):format("function", type(args.getFunc), tostring(args.getFunc)), 2)
elseif type(args.setFunc) ~= "function" then
error(("setFunc must be %q, got %q (%s)"):format("function", type(args.setFunc), tostring(args.setFunc)), 2)
elseif args.okayFunc and type(args.okayFunc) ~= "function" then
error(("okayFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.okayFunc), tostring(args.okayFunc)), 2)
elseif args.cancelFunc and type(args.cancelFunc) ~= "function" then
error(("cancelFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.cancelFunc), tostring(args.cancelFunc)), 2)
elseif args.defaultFunc and type(args.defaultFunc) ~= "function" then
error(("defaultFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.defaultFunc), tostring(args.defaultFunc)), 2)
end
for k in pairs(tmp) do
tmp[k] = nil
end
local name
local i = 0
repeat
i = i + 1
name = self:GetName() .. "_DropDown" .. i
until not _G[name]
 
local dropDown = CreateFrame("Frame", name, self, "UIDropDownMenuTemplate")
self.controls[dropDown] = true
if args.name ~= "" then
local label = dropDown:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
label:SetText(args.name)
label:SetPoint("BOTTOMLEFT", dropDown, "TOPLEFT", 16, 3)
end
dropDown.tooltipText = args.description
dropDown.values = args.values
UIDropDownMenu_Initialize(dropDown, function()
dropDown_menu(dropDown)
end)
if WotLK then
UIDropDownMenu_SetWidth(dropDown, 90)
else
UIDropDownMenu_SetWidth(90, dropDown)
end
local current
if args.getFunc then
dropDown.getFunc = args.getFunc
current = args.getFunc()
else
current = args.current
end
UIDropDownMenu_SetSelectedValue(dropDown, current)
dropDown.default = args.default
dropDown.value = args.current
dropDown.oldValue = args.current
dropDown.changeFunc = args.setFunc
dropDown.SetValue = dropDown_SetValue
dropDown:EnableMouse(true)
dropDown:SetScript("OnEnter", generic_OnEnter)
dropDown:SetScript("OnLeave", generic_OnLeave)
dropDown.okayFunc = args.okayFunc
dropDown.cancelFunc = args.cancelFunc
dropDown.defaultFunc = args.defaultFunc
args = doneArgs(args)
return dropDown
end
end
 
do
local function donothing() end
local function button_OnClick(self)
self.clickFunc()
end
--- Return a button
-- @name panel:MakeButton
-- @param ... tuple of key-value pairs<br/>
-- name: What shows above the dropdown<br/>
-- description: What shows when hovering over the dropdown<br/>
-- func: What is called when the button is pressed
-- @usage panel:MakeButton(
-- 'name', 'Click',
-- 'description', 'Specify your tooltip description',
-- 'func', function() DEFAULT_CHAT_FRAME:AddMessage("Clicked!") end
-- )
-- @return the Button
function panelMeta:MakeButton(...)
local args = getArgs(...)
if type(args.name) ~= "string" then
error(("name must be %q, got %q (%s)"):format("string", type(args.name), tostring(args.name)), 2)
elseif type(args.description) ~= "string" then
error(("description must be %q, got %q (%s)"):format("string", type(args.description), tostring(args.description)), 2)
elseif type(args.func) ~= "function" then
error(("description must be %q, got %q (%s)"):format("function", type(args.func), tostring(args.func)), 2)
end
local name
local i = 0
repeat
i = i + 1
name = self:GetName() .. "_Button" .. i
until not _G[name]
 
local button = CreateFrame("Button", name, self, "UIPanelButtonTemplate2")
self.controls[button] = true
button:SetText(args.name)
button.tooltipText = args.description
button:SetWidth(120)
button:SetHeight(22)
button.SetValue = donothing
button.clickFunc = args.func
button:SetScript("OnClick", button_OnClick)
button:SetScript("OnEnter", generic_OnEnter)
button:SetScript("OnLeave", generic_OnLeave)
args = doneArgs(args)
return button
end
end
 
do
local function toggle_SetValue(self, value)
value = not not value
self.changeFunc(value)
self.value = value
self:SetChecked(value)
end
local function toggle_OnClick(self)
self:SetValue(not not self:GetChecked())
end
--- Return a checkbox
-- @name panel:MakeToggle
-- @param ... tuple of key-value pairs<br/>
-- name: What appears to the right of the checkbox<br/>
-- description: What the tooltip shows when hovering over<br/>
-- default: The default value<br/>
-- current: The current value - you can provide this or getFunc<br/>
-- getFunc: Function to return the current value<br/>
-- setFunc: What is called when the value changes<br/>
-- [optional] okayFunc: Called when the okay button is pressed<br/>
-- [optional] cancelFunc: Called when the cancel button is pressed<br/>
-- [optional] defaultFunc: Called when the default button is pressed
-- @usage panel:MakeToggle(
-- 'name', 'Toggle',
-- 'description', 'Specify your tooltip description',
-- 'default', false,
-- 'getFunc', function() return db.myToggle end
-- 'setFunc', function(value) db.myToggle = value end
-- )
-- @return the CheckButton
function panelMeta:MakeToggle(...)
local args = getArgs(...)
if type(args.name) ~= "string" then
error(("name must be %q, got %q (%s)"):format("string", type(args.name), tostring(args.name)), 2)
elseif type(args.description) ~= "string" then
error(("description must be %q, got %q (%s)"):format("string", type(args.description), tostring(args.description)), 2)
elseif type(args.default) ~= "boolean" then
error(("default must be %q, got %q (%s)"):format("boolean", type(args.default), tostring(args.default)), 2)
elseif (args.current == nil) == not args.getFunc then
error(("either current or getFunc must be supplied, but not both"), 2)
elseif args.current and type(args.current) ~= "boolean" then
error(("current must be %q, got %q (%s)"):format("boolean", type(args.current), tostring(args.current)), 2)
elseif args.getFunc and type(args.getFunc) ~= "function" then
error(("getFunc must be %q, got %q (%s)"):format("function", type(args.getFunc), tostring(args.getFunc)), 2)
elseif type(args.setFunc) ~= "function" then
error(("setFunc must be %q, got %q (%s)"):format("function", type(args.setFunc), tostring(args.setFunc)), 2)
elseif args.okayFunc and type(args.okayFunc) ~= "function" then
error(("okayFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.okayFunc), tostring(args.okayFunc)), 2)
elseif args.cancelFunc and type(args.cancelFunc) ~= "function" then
error(("cancelFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.cancelFunc), tostring(args.cancelFunc)), 2)
elseif args.defaultFunc and type(args.defaultFunc) ~= "function" then
error(("defaultFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.defaultFunc), tostring(args.defaultFunc)), 2)
end
local name
local i = 0
repeat
i = i + 1
name = self:GetName() .. "_Toggle" .. i
until not _G[name]
 
local toggle = CreateFrame("CheckButton", name, self, "InterfaceOptionsCheckButtonTemplate")
self.controls[toggle] = true
_G[toggle:GetName() .. "Text"]:SetText(args.name)
toggle:SetHitRectInsets(0, -_G[toggle:GetName() .. "Text"]:GetWidth() - 1, 0, 0)
toggle.tooltipText = args.description
toggle.default = args.default
local current
if args.getFunc then
toggle.getFunc = args.getFunc
current = args.getFunc()
else
current = args.current
end
toggle.value = current
toggle.oldValue = current
toggle.changeFunc = args.setFunc
toggle.SetValue = toggle_SetValue
toggle:SetScript("OnClick", toggle_OnClick)
toggle:SetChecked(current)
toggle:SetScript("OnEnter", generic_OnEnter)
toggle:SetScript("OnLeave", generic_OnLeave)
toggle.okayFunc = args.okayFunc
toggle.cancelFunc = args.cancelFunc
toggle.defaultFunc = args.defaultFunc
args = doneArgs(args)
return toggle
end
end
 
do
local function update(self, r, g, b, a)
if not self.hasAlpha then
a = 1
end
self.info.r = r
self.info.g = g
self.info.b = b
if self.hasAlpha then
self.info.opacity = a
end
self.color:SetTexture(r, g, b, a)
if self.value == self.oldValue then
self.value = {}
end
self.value[1] = r
self.value[2] = g
self.value[3] = b
if self.hasAlpha then
self.value[4] = a
end
self.info.r = r
self.info.g = g
self.info.b = b
if self.hasAlpha then
self.info.opacity = 1 - a
end
if self.hasAlpha then
self.changeFunc(r, g, b, a)
else
self.changeFunc(r, g, b)
end
end
local function button_SetValue(self, ...)
if select('#', ...) == 1 and type((...)) == "table" then
return button_SetValue(self, unpack(value))
end
update(self, ...)
end
local function button_OnClick(self)
OpenColorPicker(self.info)
end
local function swatchFunc(self)
local r, g, b = ColorPickerFrame:GetColorRGB()
local opacity = 1 - OpacitySliderFrame:GetValue()
 
update(self, r, g, b, opacity)
end
local function cancelFunc(self)
local previousValues = ColorPickerFrame.previousValues
local r, g, b, opacity = previousValues.r, previousValues.g, previousValues.b, hasAlpha and 1 - previousValues.opacity or 1
 
update(self, r, g, b, opacity)
end
--- Return a color swatch that opens a color picker
-- @name panel:MakeColorPicker
-- @param ... tuple of key-value pairs<br/>
-- name: What shows up next to the swatch<br />
-- description: What shows up in the tooltip on hover<br />
-- hasAlpha: Whether the color picker should have an alpha setting<br />
-- defaultR: Default red value [0, 1]<br />
-- defaultG: Default green value [0, 1]<br />
-- defaultB: Default blue value [0, 1]<br />
-- defaultA: Default alpha value [0, 1], only needed if hasAlpha is true<br />
-- currentR: The current red value - you can provide this or getFunc<br />
-- currentG: The current green value - you can provide this or getFunc<br />
-- currentB: The current blue value - you can provide this or getFunc<br />
-- currentA: The current alpha value - you can provide this or getFunc<br />
-- getFunc: Function to return the current color as a tuple<br />
-- setFunc: What is called when the color changes<br />
-- [optional] okayFunc: Called when the okay button is pressed<br />
-- [optional] cancelFunc: Called when the cancel button is pressed<br />
-- [optional] defaultFunc: Called when the default button is pressed
-- @usage panel:MakeColorPicker(
-- 'name', 'Pick a color',
-- 'description', 'Specify your tooltip description',
-- 'hasAlpha', false,
-- 'defaultR', 1,
-- 'defaultG', 0.82,
-- 'defaultB', 0,
-- 'getFunc', function() return unpack(db.color) end
-- 'setFunc', function(r, g, b) db.color[1], db.color[2], db.color[3] = r, g, b end
-- )
-- @usage panel:MakeColorPicker(
-- 'name', 'Pick a color',
-- 'description', 'Specify your tooltip description',
-- 'hasAlpha', true,
-- 'defaultR', 0,
-- 'defaultG', 1,
-- 'defaultB', 0,
-- 'defaultA', 0.5,
-- 'currentR', db.color2.r,
-- 'currentG', db.color2.g,
-- 'currentB', db.color2.b,
-- 'currentA', db.color2.a,
-- 'setFunc', function(r, g, b, a) db.color2.r, db.color2.g db.color2.b, db.color2.a = r, g, b, a end
-- )
-- @return the color swatch
function panelMeta:MakeColorPicker(...)
local args = getArgs(...)
if type(args.name) ~= "string" then
error(("name must be %q, got %q (%s)"):format("string", type(args.name), tostring(args.name)), 2)
elseif type(args.description) ~= "string" then
error(("description must be %q, got %q (%s)"):format("string", type(args.description), tostring(args.description)), 2)
elseif type(args.hasAlpha) ~= "boolean" then
error(("hasAlpha must be %q, got %q (%s)"):format("boolean", type(args.hasAlpha), tostring(args.hasAlpha)), 2)
elseif type(args.defaultR) ~= "number" then
error(("defaultR must be %q, got %q (%s)"):format("number", type(args.defaultR), tostring(args.defaultR)), 2)
elseif args.defaultR < 0 or args.defaultR > 1 then
error(("defaultR must be [0, 1], got %s"):format(tostring(args.defaultR)), 2)
elseif type(args.defaultG) ~= "number" then
error(("defaultG must be %q, got %q (%s)"):format("number", type(args.defaultG), tostring(args.defaultG)), 2)
elseif args.defaultG < 0 or args.defaultG > 1 then
error(("defaultG must be [0, 1], got %s"):format(tostring(args.defaultG)), 2)
elseif type(args.defaultB) ~= "number" then
error(("defaultB must be %q, got %q (%s)"):format("number", type(args.defaultB), tostring(args.defaultB)), 2)
elseif args.defaultB < 0 or args.defaultB > 1 then
error(("defaultB must be [0, 1], got %s"):format(tostring(args.defaultB)), 2)
elseif args.hasAlpha and type(args.defaultA) ~= "number" then
error(("defaultA must be %q, got %q (%s)"):format("number", type(args.defaultA), tostring(args.defaultA)), 2)
elseif args.hasAlpha and (args.defaultA < 0 or args.defaultA > 1) then
error(("defaultA must be [0, 1], got %s"):format(tostring(args.defaultA)), 2)
elseif not args.currentR == not args.getFunc then
error(("either currentR or getFunc must be supplied, but not both"), 2)
elseif args.currentR and (not args.currentG or not args.currentB or (args.hasAlpha and not args.currentA)) then
error(("if you supply currentR, you must supply currentG and currentB (and currentA if hasAlpha)"), 2)
elseif args.currentR and type(args.currentR) ~= "number" then
error(("current must be %q, got %q (%s)"):format("number", type(args.currentR), tostring(args.currentR)), 2)
elseif args.currentG and type(args.currentG) ~= "number" then
error(("current must be %q, got %q (%s)"):format("number", type(args.currentG), tostring(args.currentG)), 2)
elseif args.currentB and type(args.currentB) ~= "number" then
error(("current must be %q, got %q (%s)"):format("number", type(args.currentB), tostring(args.currentB)), 2)
elseif args.currentA and type(args.currentA) ~= "number" then
error(("current must be %q, got %q (%s)"):format("number", type(args.currentA), tostring(args.currentA)), 2)
elseif args.getFunc and type(args.getFunc) ~= "function" then
error(("getFunc must be %q, got %q (%s)"):format("function", type(args.getFunc), tostring(args.getFunc)), 2)
elseif type(args.setFunc) ~= "function" then
error(("setFunc must be %q, got %q (%s)"):format("function", type(args.setFunc), tostring(args.setFunc)), 2)
elseif args.okayFunc and type(args.okayFunc) ~= "function" then
error(("okayFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.okayFunc), tostring(args.okayFunc)), 2)
elseif args.cancelFunc and type(args.cancelFunc) ~= "function" then
error(("cancelFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.cancelFunc), tostring(args.cancelFunc)), 2)
elseif args.defaultFunc and type(args.defaultFunc) ~= "function" then
error(("defaultFunc must be %q or %q, got %q (%s)"):format("nil", "function", type(args.defaultFunc), tostring(args.defaultFunc)), 2)
end
 
local name
local i = 0
repeat
i = i + 1
name = self:GetName() .. "_ColorPicker" .. i
until not _G[name]
 
if not args.hasAlpha then
args.defaultA = 1
end
 
local button = CreateFrame("Button", name, self)
self.controls[button] = true
 
 
local currentR, currentG, currentB, currentA
if args.getFunc then
button.getFunc = args.getFunc
currentR, currentG, currentB, currentA = button.getFunc()
if not args.hasAlpha then
currentA = 1
end
else
currentR = args.currentR
currentG = args.currentG
currentB = args.currentB
if not args.hasAlpha then
currentA = 1
else
currentR = args.currentA
end
end
 
button.tooltipText = args.description
local text = button:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
text:SetText(args.name)
text:SetPoint("LEFT", button, "RIGHT", 0, 1)
button:SetHitRectInsets(0, -text:GetWidth() - 1, 0, 0)
local color = button:CreateTexture(nil, "ARTWORK")
button.color = color
color:SetTexture(currentR, currentG, currentB, currentA)
local background = button:CreateTexture(nil, "BORDER")
background:SetTexture([=[Tileset\Generic\Checkers]=])
background:SetTexCoord(0, 0.5, 0, 0.5)
local border = button:CreateTexture(nil, "BACKGROUND")
border:SetTexture([=[Interface\ChatFrame\ChatFrameColorSwatch]=])
button:SetWidth(26)
button:SetHeight(26)
background:SetPoint("CENTER")
background:SetWidth(14)
background:SetHeight(14)
color:SetPoint("CENTER")
color:SetWidth(14)
color:SetHeight(14)
border:SetAllPoints(button)
button.default = { args.defaultR, args.defaultG, args.defaultB }
button.oldValue = { currentR, currentG, currentB }
if hasAlpha then
button.default[4] = args.defaultA
button.oldValue[4] = currentA
end
button.value = button.oldValue
button.hasAlpha = args.hasAlpha
button.changeFunc = args.setFunc
button.SetValue = button_SetValue
local function swatchFunc_wrapper()
swatchFunc(button)
end
local function cancelFunc_wrapper()
cancelFunc(button)
end
button.info = {
swatchFunc = swatchFunc_wrapper,
hasOpacity = args.hasAlpha,
opacityFunc = args.hasAlpha and swatchFunc_wrapper or nil,
r = currentR,
g = currentB,
b = currentG,
opacity = args.hasAlpha and 1 - currentA or nil,
cancelFunc = cancelFunc_wrapper,
}
button:SetScript("OnClick", button_OnClick)
button:SetScript("OnEnter", generic_OnEnter)
button:SetScript("OnLeave", generic_OnLeave)
button:RegisterForClicks("LeftButtonUp")
button.okayFunc = args.okayFunc
button.cancelFunc = args.cancelFunc
button.defaultFunc = args.defaultFunc
args = doneArgs(args)
return button
end
end
 
--- Add a slash command to open a specific options panel
-- @param name name of the panel to open
-- @param ... tuple of slash commands
-- @usage LibStub("LibSimpleOptions-1.0").AddSlashCommand("My Options", "/MyOpt", "/MO")
function LibSimpleOptions.AddSlashCommand(name, ...)
local num = 0
local name_upper = name:upper()
for i = 1, select('#', ...) do
local cmd = select(i, ...)
num = num + 1
_G["SLASH_" .. name_upper .. num] = cmd
local cmd_lower = cmd:lower()
if cmd_lower ~= cmd then
num = num + 1
_G["SLASH_" .. name_upper .. num] = cmd_lower
end
end
 
_G.hash_SlashCmdList[name_upper] = nil
_G.SlashCmdList[name_upper] = function()
InterfaceOptionsFrame_OpenToCategory(name)
end
end
 
for funcName, func in pairs(panelMeta) do
LibSimpleOptions[funcName] = func
for panel in pairs(panels) do
panel[funcName] = func
end
end
\ No newline at end of file