local MAJOR = "LibDropdown-1.0" local MINOR = 1 local lib = LibStub:NewLibrary(MAJOR, MINOR) if not lib then return end local math_max = _G.math.max local framePool = lib.framePool or {} lib.framePool = framePool local buttonPool = lib.buttonPool or {} lib.buttonPool = buttonPool local inputPool = lib.inputPool or {} lib.inputPool = inputPool local frameHideQueue = lib.frameHideQueue or {} lib.frameHideQueue = frameHideQueue local sliderPool = lib.sliderPool or {} lib.sliderPool = sliderPool local AddButton, ShowGroup, HideGroup, SetGroup, NewDropdownFrame, NewDropdownButton, ReleaseFrame, AcquireButton, ReleaseButton, AcquireFrame local UIParent = _G.UIParent local openMenu local noop = lib.noop or function() end lib.noop = noop local new, newHash, newSet, del if not lib.new then local list = setmetatable({}, {__mode='k'}) function new(...) local t = next(list) if t then list[t] = nil for i = 1, select('#', ...) do t[i] = select(i, ...) end return t else return {...} end end function del(t) setmetatable(t, nil) for k in pairs(t) do t[k] = nil end t[''] = true t[''] = nil list[t] = true return nil end lib.new, lib.del = new, del end -- Make the frame match the tooltip local function InitializeFrame(frame) local backdrop = GameTooltip:GetBackdrop() frame:SetBackdrop(backdrop) if backdrop then frame:SetBackdropColor(GameTooltip:GetBackdropColor()) frame:SetBackdropBorderColor(GameTooltip:GetBackdropBorderColor()) end frame:SetScale(GameTooltip:GetScale()) end local editBoxCount = 1 local function AcquireInput() local frame = tremove(inputPool) if frame then frame.released = false return frame end frame = CreateFrame("EditBox", "LibDropDownEditBox"..editBoxCount, UIParent, "InputBoxTemplate") frame:SetAutoFocus(false) editBoxCount = editBoxCount + 1 frame:SetScript("OnEscapePressed", function(self) self:ClearFocus() self:GetParent():GetRoot():Refresh() end) frame:SetScript("OnEnterPressed", function(self) if self.ValueChanged then self:ValueChanged(self:GetText()) end end) frame.refresh = noop return frame end local function AcquireSlider() local frame = tremove(sliderPool) if frame then frame.released = false return frame end local frame = CreateFrame("Slider", nil, UIParent) frame:SetWidth(10) frame:SetHeight(150) frame:SetOrientation("VERTICAL") frame:SetBackdrop({ bgFile = [[Interface\Buttons\UI-SliderBar-Background]], edgeFile = [[Interface\Buttons\UI-SliderBar-Border]], tile = true, tileSize = 8, edgeSize = 8, insets = {left = 3, right = 3, top = 6, bottom = 6} }) frame:SetThumbTexture([[Interface\Buttons\UI-SliderBar-Button-Vertical]]) frame:EnableMouseWheel() frame:Show() local text = frame:CreateFontString(nil, nil, "GameFontNormalSmall") text:SetPoint("TOP", frame, "BOTTOM") text:SetTextColor(1,1,1,1) frame.text = text frame:SetScript("OnMouseWheel", function(self, direction, ...) if not direction then return end -- huh? local mn, mx = self:GetMinMaxValues() local nv = min(mx, max(mn, self:GetValue() + ((self.step or 1) * direction * -1))) self:SetValue(nv) end) frame:SetScript("OnValueChanged", function(self) local mn, mx = self:GetMinMaxValues() local nv = min(mx, max(mn, self:GetValue())) if nv ~= self:GetValue() then self:SetValue(nv) return end local n, x = self:GetMinMaxValues() local ev = x - nv frame.text:SetText(ev) if self.ValueChanged then self:ValueChanged(self:GetValue()) end end) frame.refresh = noop return frame end local function ReleaseSlider(slider) if slider.released then return end slider.released = true slider:Hide() slider:SetParent(UIParent) tinsert(sliderPool, slider) return nil end local function ReleaseInput(input) if input.released then return end input.released = true input:Hide() input:SetParent(UIParent) tinsert(inputPool, input) return nil end local function MouseOver(frame) local f = GetMouseFocus() while f and f ~= UIParent do if f == frame then return true end f = f:GetParent() end return false end -- Frame methods function AddButton(self, b) b:ClearAllPoints() b:SetParent(self) b:Show() if #self.buttons == 0 then b:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -4) b:SetPoint("TOPRIGHT", self, "TOPRIGHT", 0, -4) else b:SetPoint("TOPLEFT", self.buttons[#self.buttons], "BOTTOMLEFT") b:SetPoint("TOPRIGHT", self.buttons[#self.buttons], "BOTTOMRIGHT") end tinsert(self.buttons, b) self:SetHeight(#self.buttons * b:GetHeight() + 8) end function Refresh(self) if not self:IsVisible() then return end local maxWidth = 1 for i = 1, #self.buttons do self.buttons[i]:refresh() maxWidth = math_max(maxWidth, self.buttons[i].text:GetStringWidth() + 60) end self:SetWidth(maxWidth) end function GetRoot(self) local parent = self:GetParent() if parent and parent.GetRoot then return parent:GetRoot() else return self end end -- Button methods function ShowGroup(self) if not self.enabled then return end if not self.groupFrame then self.groupFrame = self:AcquireFrame() end if not self.handled then self.handler(lib, self.group, self.groupFrame) self.handled = true end self.groupFrame:SetPoint("TOPLEFT", self, "TOPRIGHT", 0, 4) self.groupFrame:Show() self.groupFrame:Refresh() self:LockHighlight() self:enter() if self.groupFrame.Showing then self.groupFrame:Showing() end end function HideGroup(self) if not self then return end if MouseOver(self) then return end if self.groupFrame then self.groupFrame:Hide() end self:UnlockHighlight() self:leave() if self.groupFrame.Hiding then self.groupFrame:Hiding() end end function SetChecked(self, val) self.checked = val if val then self.check:Show() self.check:SetDesaturated(false) elseif val == false or not self.tristate then self.check:Hide() elseif val == nil then self.check:Show() self.check:SetDesaturated(true) end end function HideRecursive(self) HideGroup(self:GetParent()) end function SetGroup(self, t, handler) if t then self.expand:Show() self:SetScript("OnEnter", ShowGroup) self:SetScript("OnLeave", HideGroup) self.group = t self.handler = handler else self.expand:Hide() self:SetScript("OnEnter", nil) self:SetScript("OnLeave", nil) self.group = nil self.handler = nil end self.clickable = t == nil end -- Pool methods local frameCount = 0 function NewDropdownFrame() local frame = CreateFrame("Frame", "LibDropdownFrame" .. frameCount, UIParent) frameCount = frameCount + 1 frame:SetPoint("CENTER", UIParent, "CENTER") frame:SetWidth(10) frame:SetHeight(24) frame:EnableMouse(true) frame.AddButton = AddButton frame.Refresh = Refresh frame.GetRoot = GetRoot frame.isDropdownFrame = true frame.Release = ReleaseFrame frame.AcquireButton = AcquireButton -- make it close on escape tinsert(UISpecialFrames, frame:GetName()) return frame end do local function enterButton(self) GameTooltip_SetDefaultAnchor(GameTooltip, self) GameTooltip:ClearLines() GameTooltip:AddLine(self.text:GetText()) if self.desc then GameTooltip:AddLine("|cffffffff" .. self.desc .. "|r") end GameTooltip:Show() end local function leaveButton(self) GameTooltip:Hide() local p = self:GetParent() if p then local f = p:GetScript("OnLeave") if f then f(p) end end end local function pushText(self) if not self.clickable then return end self.text:SetPoint("TOP", self, "TOP", 0, -2) self.text:SetPoint("LEFT", self.check, "RIGHT", 6, 0) end local function unpushText(self) if not self.clickable then return end self.text:SetPoint("TOP", self, "TOP", 0, 0) self.text:SetPoint("LEFT", self.check, "RIGHT", 4, 0) end local function click(self) if self.OnClick and self.clickable then self.OnClick(self) PlaySound("igMainMenuOptionCheckBoxOn"); self:GetParent():GetRoot():Refresh() end end local function settext(self, t) self.text:SetText(t) end local function disable(self) self.enabled = false self:SetScript("OnMouseDown", nil) self:SetScript("OnMouseUp", nil) self.text:SetTextColor(0.5, 0.5, 0.5, 1) self.check:SetDesaturated(true) self.expand:SetDesaturated(true) self:oldDisable() end local function enable(self) self.enabled = true self:SetScript("OnMouseDown", pushText) self:SetScript("OnMouseUp", unpushText) self.text:SetTextColor(1, 1, 1, 1) -- self.text:SetTextColor(self:GetTextColor()) -- Removed in 3.0 self.check:SetDesaturated(false) self.expand:SetDesaturated(false) self:oldEnable() end local function revert() --ColorPickerFrame.previousValues.frame end local function setColor() local r,g,b = ColorPickerFrame:GetColorRGB() local a = ColorPickerFrame.opacity or 1 local f = ColorPickerFrame.previousValues.frame f:GetNormalTexture():SetVertexColor(r, g, b, a) if f:GetParent().OnClick then f:GetParent():OnClick(r,g,b,a) end end local function revert() p = ColorPickerFrame.previousValues ColorPickerFrame:SetColorRGB(p.r, p.g, p.b) ColorPickerFrame.opacity = p.opacity setColor() end local function openColorPicker(self) local p = self:GetParent() p.r, p.g, p.b, p.a = self:GetNormalTexture():GetVertexColor() ColorPickerFrame.hasOpacity = p.hasOpacity ColorPickerFrame.opacityFunc = p.opacityFunc ColorPickerFrame.opacity = p.a ColorPickerFrame:SetColorRGB(p.r, p.g, p.b) ColorPickerFrame.previousValues = ColorPickerFrame.previousValues or {} ColorPickerFrame.previousValues.r = p.r ColorPickerFrame.previousValues.g = p.g ColorPickerFrame.previousValues.b = p.b ColorPickerFrame.previousValues.opacity = p.a ColorPickerFrame.previousValues.frame = self ColorPickerFrame.cancelFunc = revert ColorPickerFrame.func = setColor ShowUIPanel(ColorPickerFrame) end local function highlightSwatch(self) self.tex:SetTexture(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b); end local function unhighlightSwatch(self) self.tex:SetTexture(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); end local function makeTitle(self, t) -- self.text:SetJustifyH("CENTER") self.text:ClearAllPoints() self.text:SetPoint("LEFT", self, "LEFT", 16, 0) self.text:SetPoint("RIGHT", self, "RIGHT", -16, 0) self.text:SetTextColor(1, 0.8, 0, 1) self.clickable = false if t then self.text:SetText(t) end end local function makeButton(self, t) local text, frame, check, expand = self.text, self, self.check, self.expand text:ClearAllPoints() text:SetPoint("TOP", frame, "TOP") text:SetPoint("LEFT", check, "RIGHT", 4, 0) text:SetPoint("BOTTOM", frame, "BOTTOM") text:SetPoint("RIGHT", expand, "LEFT", -4, 0) text:SetJustifyH("LEFT") self.text:SetTextColor(1, 1,1,1) self.clickable = true if t then text:SetText(t) end end function NewDropdownButton(f) local frame = f or CreateFrame("Button", nil, UIParent) frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]]) frame:GetHighlightTexture():SetBlendMode("ADD") -- frame:SetDisabledTextColor(0.5, 0.5, 0.5, 1) -- Removed in 3.0 frame:SetPushedTextOffset(3,-3) frame:SetHeight(18) local check = frame.check or frame:CreateTexture() check:SetTexture([[Interface\Buttons\UI-CheckBox-Check]]) check:SetWidth(18) check:SetHeight(18) check:SetPoint("LEFT", frame, "LEFT", 4, 0) check:Hide() frame.check = check local expand = frame.expand or frame:CreateTexture() expand:SetTexture([[Interface\ChatFrame\ChatFrameExpandArrow]]) expand:SetWidth(16) expand:SetHeight(16) expand:SetPoint("RIGHT", frame, "RIGHT", -4, 0) expand:Hide() frame.expand = expand local text = frame.text or frame:CreateFontString(nil, nil, "GameFontHighlightSmall") frame.text = text frame.SetText = settext frame.MakeButton = makeButton frame.MakeTitle = makeTitle frame:MakeButton("<not set>") local swatch = frame.swatch or CreateFrame("Button", nil, frame) swatch:SetWidth(18) swatch:SetHeight(18) swatch.tex = swatch.text or swatch:CreateTexture(nil, "BACKGROUND") swatch.tex:SetPoint("CENTER", swatch, "CENTER") swatch.tex:SetWidth(swatch:GetWidth()-2) swatch.tex:SetHeight(swatch:GetHeight()-2) -- swatch.tex:SetTexture([[Interface\ChatFrame\ChatFrameColorSwatch]]) swatch:SetNormalTexture([[Interface\ChatFrame\ChatFrameColorSwatch]]) swatch:SetPoint("RIGHT", frame, "RIGHT", -4, 0) swatch:SetScript("OnClick", openColorPicker) swatch:SetFrameLevel(frame:GetFrameLevel() + 100) swatch:SetScript("OnEnter", highlightSwatch) swatch:SetScript("OnLeave", unhighlightSwatch) swatch:Hide() frame.swatch = swatch unhighlightSwatch(swatch) frame:SetScript("OnEnter", enterButton) frame:SetScript("OnLeave", leaveButton) frame.enter, frame.leave = enterButton, leaveButton frame:SetScript("OnMouseDown", pushText) frame:SetScript("OnMouseUp", unpushText) frame:SetScript("OnClick", click) frame.SetGroup = SetGroup frame.SetChecked = SetChecked frame.AcquireFrame = AcquireFrame frame.GetRoot = GetRoot frame.oldDisable, frame.Disable = frame.Disable, disable frame.oldEnable, frame.Enable = frame.Enable, enable frame.Release = ReleaseButton frame.clickable = true frame.enabled = true frame:Enable() return frame end end function ReleaseFrame(f) if f.rootMenu then openMenu = nil end if f.released then return end f.released = true f.data = nil f.dataname = nil f.rootMenu = nil f:Hide() f:SetParent(UIParent) f:ClearAllPoints() tinsert(framePool, f) for i = 1, #f.buttons do local button = tremove(f.buttons) button:Release() end return nil end function AcquireButton(p) local b = NewDropdownButton(tremove(buttonPool)) b.released = false b:EnableMouse(true) b:Show() p:AddButton(b) return b end function ReleaseButton(b) if b.released then return end tinsert(buttonPool, b) b.desc = nil b.released = true b.Enable = b.oldEnable b.Disable = b.oldDisable b.handled = false b:SetParent(UIParent) b:Hide() if b.slider then b.slider = ReleaseSlider(b.slider) end if b.input then b.input = ReleaseInput(b.input) end b:ClearAllPoints() b:MakeButton("(released)") if b.groupFrame then b.groupFrame.Showing = nil b.groupFrame = b.groupFrame:Release() end end local function frameReleaseOnHide(self) self:SetScript("OnHide", nil) self:Release() end function AcquireFrame(parent, toplevel) local f = tremove(framePool) or NewDropdownFrame() InitializeFrame(f) -- set the look of the frame f.released = false f.buttons = f.buttons or {} f:SetParent(parent or UIParent) if parent then f:SetScript("OnLeave", HideRecursive) else f:SetScript("OnLeave", nil) end if toplevel then f:SetScript("OnHide", frameReleaseOnHide) else f:SetScript("OnHide", nil) end f:ClearAllPoints() f:Show() return f end ---------------------------------------------------------------------- ---------------------------------------------------------------------- do local Ace3 = {} local grefresh local info = {} local options local currentOptionData local function setup(k, v, parent) local b = parent:AcquireButton() b.data = v b.option = v b.dataname = k b.refresh = grefresh return b end local function setInfoOptions() local option = options for _, key in ipairs(info) do if option.args and option.args[key] then option = option.args[key] else return end end info.option = option info.type = option.type end local function initInfo(type) info.options = options info.appName = options.name info.type = type info.uiType = "dropdown" info.uiName = "LibDropdown-1.0" end local function wipeInfo() local type = info.type wipe(info) initInfo(type) end local function runHandler(button, handler, ...) info.handler = handler info.option = button.data if not button.rootMenu then tinsert(info, 1, button.dataname) end local v = button.data if v and v[handler] then local ht = type(v[handler]) if ht == "function" then setInfoOptions() local ret, r1, r2, r3 = v[handler](info, ...) wipeInfo() return ret, r1, r2, r3 elseif ht == "table" then return v[handler] elseif ht == "string" then local t = runHandler(button, "handler", ...) if type(t) == "table" then setInfoOptions() local ret, r1, r2, r3 = t[v[handler]](t, info, ...) wipeInfo() return ret, r1, r2, r3 end end elseif v and v[handler] == false then return nil -- Is this right? else if button.GetParent then local pp = button:GetParent() and button:GetParent():GetParent() if not pp or not pp.data then pp = button:GetParent() end if pp and pp.data then return runHandler(pp, handler, ...) end end end wipeInfo() return nil end function grefresh(self) local isDisabled = false self:SetText(self.data.name) self.desc = self.data.desc if type(self.data.disabled) == "function" then if self.data.disabled() then self:Disable() isDisabled = true else self:Enable() end elseif type(self.data.disabled) == "boolean" then if self.data.disabled then self:Disable() isDisabled = true else self:Enable() end end return isDisabled end -- group do local function refresh(self) grefresh(self) if not self.groupFrame or self.groupFrame == self:GetParent() then return end self.groupFrame:Refresh() end function Ace3.group(k, v, parent) local b = setup(k, v, parent) if v.inline then -- TODO: Add heading local b2 = parent:AcquireButton() b:MakeTitle(k) b2.refresh = noop lib:OpenAce3Menu(v.args, parent) else b:SetGroup(v.args, lib.OpenAce3Menu) end b.refresh = refresh end end -- execute function Ace3.execute(k, v, parent) local b = setup(k, v, parent) b:SetText(v.name) b.desc = v.desc b.OnClick = function(self) initInfo('execute') runHandler(self, "func") self:GetRoot():Refresh() end end -- input do local function refresh(self) grefresh(self) self.input:SetText(runHandler(self, "get") or "") end local function inputValueChanged(self, val) initInfo('input') runHandler(self:GetParent():GetParent(), "set", val) self:GetParent():GetRoot():Refresh() end function Ace3.input(k, v, parent) local b = setup(k, v, parent) b:SetGroup(v, lib.Ace3InputShow) b.input = AcquireInput() b.refresh = refresh end local function showInput(frame) local data = frame.data local input = frame:GetParent().input input:SetParent(frame) input:ClearAllPoints() input:SetPoint("LEFT", frame, "LEFT", 10, 0) frame:SetWidth(185) input:SetWidth(170) input:SetHeight(34) frame:SetHeight(34) input.ValueChanged = inputValueChanged input:Show() refresh(frame:GetParent()) end function lib:Ace3InputShow(t, parent) parent.data = t parent.Showing = showInput end end -- toggle do local function refresh(self) local disabled = grefresh(self) initInfo('toggle') local actual = runHandler(self, "get") if disabled then self:SetChecked(false) else self:SetChecked(actual) end end local function onClick(self) initInfo('toggle') if self.data.tristate then local val = runHandler(self, "get") local sv if val == nil then sv = true elseif val == true then sv = false else sv = nil end runHandler(self, "set", sv) else local val = not runHandler(self, "get") runHandler(self, "set", val) end self:GetRoot():Refresh() end function Ace3.toggle(k, v, parent) local b = setup(k, v, parent) b.OnClick = onClick b.tristate = v.tristate b.refresh = refresh end end -- header do local function refresh(self) grefresh(self) end function Ace3.header(k, v, parent) local b = setup(k, v, parent) b:MakeTitle(k) b:EnableMouse(false) b.tristate = nil b.refresh = refresh end end -- color do local function refresh(self) grefresh(self) initInfo('color') self.swatch:GetNormalTexture():SetVertexColor(runHandler(self, "get")) end function Ace3.color(k, v, parent) local b = setup(k, v, parent) b.swatch:Show() b.clickable = false b.refresh = refresh b.OnClick = function(self, r, g, b, a) runHandler(self, "set", r, g, b, a); self:GetRoot():Refresh() end end end -- select do local function refresh(self) grefresh(self) if self.groupFrame then self.groupFrame:Refresh() end end function Ace3.select(k, v, parent) local b = setup(k, v, parent) b.parentTree = v b:SetGroup(v.values, lib.Ace3MenuSelect) b.refresh = refresh end local function buttonRefresh(self) initInfo('select') self:SetChecked( runHandler(self:GetParent():GetParent(), "get") == self.value ) end function lib:Ace3MenuSelect(t, parent) initInfo('select') if type(t) == "string" or type(t) == "function" then t = runHandler(parent, "values") end if type(t) == "table" then for k, v in pairs(t) do local b = parent:AcquireButton() b:SetText(v) b.value = k b.OnClick = function(self) initInfo('select') runHandler(self:GetParent():GetParent(), "set", self.value) self:GetParent():GetRoot():Refresh() end b.refresh = buttonRefresh end end end end -- range -- Some extra tricksery for mousewheel on the containing frame. A bit more user friendly. do local function refresh(self) grefresh(self) initInfo('range') self.slider:SetValue(runHandler(self, "get") or self.slider:GetMinMaxValues()) initInfo('range') self.slider.text:SetText(runHandler(self, "get")) end function Ace3.range(k, v, parent) local b = setup(k, v, parent) b:SetGroup(v, lib.Ace3SliderShow) b.slider = AcquireSlider() b.refresh = refresh end local function onWheel(f) f:GetParent().slider:GetScript("OnMouseWheel")(f:GetParent().slider) end local function removeMousewheelFuncs(f) tremove(f.buttons) f:EnableMouseWheel(false) f:SetScript("OnMouseWheel", nil) f.Hiding = nil end local function sliderValueChanged(self, val) initInfo('range') runHandler(self:GetParent():GetParent(), "set", val) self:GetParent():GetRoot():Refresh() end local function showSlider(frame) local data = frame.data local slider = frame:GetParent().slider slider:SetParent(frame) slider:ClearAllPoints() slider:SetPoint("CENTER", frame, "CENTER") slider:SetPoint("TOP", frame, "TOP", 0, -8) slider:SetHeight(150) slider.text:ClearAllPoints() slider.text:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 8) slider.text:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 8) slider.text:SetText(data.max) frame:SetWidth(max(60, slider.text:GetStringWidth() + 10)) slider.step = data.bigStep slider:SetMinMaxValues(data.min or 0, data.max or 100) slider:SetValueStep(data.bigStep or data.step or 1) slider.ValueChanged = sliderValueChanged frame:EnableMouseWheel(true) frame:SetScript("OnMouseWheel", onWheel) frame.Hiding = removeMousewheelFuncs frame:SetHeight(180) slider:Show() refresh(frame:GetParent()) end function lib:Ace3SliderShow(t, parent) parent.data = t parent.Showing = showSlider end end do local sortOptions = function(a,b) if (b.order or 100) > (a.order or 100) then return true elseif (b.order or 100) < (a.order or 100) then return false elseif b.name:lower() > a.name:lower() then return true else return false end end function lib:OpenAce3Menu(t, parent) assert(t and type(t) == "table", "Expected table, got "..type(t)) if parent == nil and t.args then if openMenu then openMenu:Release() end options = t openMenu = AcquireFrame(nil, true) openMenu:Show() openMenu.data = t openMenu.dataname = "Root menu" openMenu.rootMenu = true openMenu:SetPoint("CENTER", UIParent, "CENTER") self:OpenAce3Menu(t.args, openMenu) openMenu:Refresh() openMenu:SetFrameStrata("TOOLTIP") return openMenu else local sortedOpts = new() local lookup = new() for i = 1, #sortedOpts do tremove(sortedOpts) end for k, v in pairs(t) do lookup[v] = k tinsert(sortedOpts, v) end table.sort(sortedOpts, sortOptions) for _, v in ipairs(sortedOpts) do if Ace3[v.type] and not v.dropdownHidden and not v.hidden then Ace3[v.type](lookup[v], v, parent) end end sortedOpts = del(sortedOpts) lookup = del(lookup) end end end end ------------------------------------------------------ ------------------------------------------------------ local toggled = true local r,g,b,a = 1,0,1,1 local options = {"foo", "bar", "foobar"} local optIndex = 1 local rangeVal, rangeVal2 = 100, 10 local inherits = {["inherittoggle"] = true} local t = { type = "group", name = "group", desc = "group", args = { foo = { type = "input", name = "text", desc = "text desc", get = function(info) return "texting!" end, set = function(info, v) end }, inherit = { type = "group", name = "inheritance test", desc = "inheritance test", get = function(info) ChatFrame1:AddMessage(("Got getter, getting %s (%s)"):format(tostring(info[#info]), tostring(inherits[info[#info]]))); return inherits[info[#info]] end, set = function(info, v) ChatFrame1:AddMessage("Got setter:" .. tostring(v)); inherits[info[#info]] = v end, args = { inherittoggle = { type = "toggle", name = "inherit toggle", desc = "inherit toggle" }, } }, exec = { type = "execute", name = "Say hi", desc = "Execute, says hi", func = function() ChatFrame1:AddMessage("Hi!") end }, range = { type = "range", name = "Range slider", desc = "Range slider", min = 0, max = 800, bigStep = 50, get = function(info) return rangeVal end, set = function(info, v) rangeVal = v end, }, range2 = { type = "range", name = "Range slider 2", desc = "Range slider 2", min = 0, max = 80, bigStep = 5, get = function(info) return rangeVal2 end, set = function(info, v) rangeVal2 = v end, }, toggle = { type = "toggle", name = "Toggle", desc = "Toggle", get = function() return toggled end, set = function(info, v) toggled = v end, disabled = function(info) return not toggled end }, toggle3 = { type = "toggle", name = "Tristate Toggle Tristate Toggle Tristate Toggle", desc = "Tristate Toggle", tristate = true, get = function() return toggled end, set = function(info, v) toggled = v end }, select = { type = "select", name = "select", desc = "select desc", values = options, get = function(info) return optIndex end, set = function(info, v) optIndex = v end }, color = { type = "color", name = "color swatch", desc = "color swatch desc", get = function(info) return r,g,b,a end, set = function(info, _r,_g,_b,_a) r,g,b,a = _r,_g,_b,_a end }, foo3 = { type = "group", name = "group!", desc = "group desc", args = { toggle3 = { type = "toggle", name = "Tristate Toggle Tristate Toggle Tristate Toggle", desc = "Tristate Toggle", tristate = true, get = function() return toggled end, set = function(info, v) toggled = v end }, } }, foo4 = { type = "group", name = "inline group!", desc = "inline group desc", inline = "true", args = { foo2 = { type = "input", name = "text3", desc = "text3 desc", get = function(info) return "texting!" end, set = function(info, v) end } }, order = 500 }, close = { type = "execute", name = "Close", desc = "Close this menu", func = function(self) end, order = 1000 } } } function testdropdown() LibStub("LibDropdown-1.0"):OpenAce3Menu(t) end ---- WorldFrame:HookScript("OnMouseDown", function() if openMenu then openMenu = openMenu:Release() end end)