local MAJOR_VERSION = "1.0" local MINOR_VERSION = tonumber(string.sub("$Revision: 1613 $", 12, -3)) if DewdropLib and DewdropLib.versions[MAJOR_VERSION] and DewdropLib.versions[MAJOR_VERSION].minor >= MINOR_VERSION then return end -------------IRIEL'S-STUB-CODE-------------- local stub = {}; -- Instance replacement method, replace contents of old with that of new function stub:ReplaceInstance(old, new) for k,v in pairs(old) do old[k]=nil; end for k,v in pairs(new) do old[k]=v; end end -- Get a new copy of the stub function stub:NewStub() local newStub = {}; self:ReplaceInstance(newStub, self); newStub.lastVersion = ''; newStub.versions = {}; return newStub; end -- Get instance version function stub:GetInstance(version) if (not version) then version = self.lastVersion; end local versionData = self.versions[version]; if (not versionData) then message("Cannot find library instance with version '" .. version .. "'"); return; end return versionData.instance; end -- Register new instance function stub:Register(newInstance) local version,minor = newInstance:GetLibraryVersion(); self.lastVersion = version; local versionData = self.versions[version]; if (not versionData) then -- This one is new! versionData = { instance = newInstance, minor = minor, old = {} }; self.versions[version] = versionData; newInstance:LibActivate(self); return newInstance; end if (minor <= versionData.minor) then -- This one is already obsolete if (newInstance.LibDiscard) then newInstance:LibDiscard(); end return versionData.instance; end -- This is an update local oldInstance = versionData.instance; local oldList = versionData.old; versionData.instance = newInstance; versionData.minor = minor; local skipCopy = newInstance:LibActivate(self, oldInstance, oldList); table.insert(oldList, oldInstance); if (not skipCopy) then for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance); end end return newInstance; end -- Bind stub to global scope if it's not already there if (not DewdropLib) then DewdropLib = stub:NewStub(); end -- Nil stub for garbage collection stub = nil; -----------END-IRIEL'S-STUB-CODE------------ local function assert(condition, message) if not condition then local stack = debugstack() local first = string.gsub(stack, "\n.*", "") local file = string.gsub(first, "^(.*\\.*)%.lua:%d+: .*", "%1") if not message then local _,_,second = string.find(stack, "\n(.-)\n") message = "assertion failed! " .. second end local i = 1 for s in string.gfind(stack, "\n(.-)\n") do i = i + 1 if not string.find(s, file .. "%.lua:%d+:") then error(message, i) return end end error(message, 2) return end return condition end local lib = {} local ipairs = ipairs local tinsert = table.insert local tremove = table.remove local tgetn = table.getn local function new(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) local t = {} if k1 then t[k1] = v1 if k2 then t[k2] = v2 if k3 then t[k3] = v3 if k4 then t[k4] = v4 if k5 then t[k5] = v5 if k6 then t[k6] = v6 if k7 then t[k7] = v7 if k8 then t[k8] = v8 if k9 then t[k9] = v9 if k10 then t[k10] = v10 if k11 then t[k11] = v11 if k12 then t[k12] = v12 if k13 then t[k13] = v13 if k14 then t[k14] = v14 if k15 then t[k15] = v15 if k16 then t[k16] = v16 if k17 then t[k17] = v17 if k18 then t[k18] = v18 if k19 then t[k19] = v19 if k20 then t[k20] = v20 end end end end end end end end end end end end end end end end end end end end return t end local tmp do local t function tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) for k in pairs(t) do t[k] = nil end if k1 then t[k1] = v1 if k2 then t[k2] = v2 if k3 then t[k3] = v3 if k4 then t[k4] = v4 if k5 then t[k5] = v5 if k6 then t[k6] = v6 if k7 then t[k7] = v7 if k8 then t[k8] = v8 if k9 then t[k9] = v9 if k10 then t[k10] = v10 if k11 then t[k11] = v11 if k12 then t[k12] = v12 if k13 then t[k13] = v13 if k14 then t[k14] = v14 if k15 then t[k15] = v15 if k16 then t[k16] = v16 if k17 then t[k17] = v17 if k18 then t[k18] = v18 if k19 then t[k19] = v19 if k20 then t[k20] = v20 end end end end end end end end end end end end end end end end end end end end return t end local x = tmp function tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) t = {} tmp = x x = nil return tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) end end local tmp2 do local t function tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) for k in pairs(t) do t[k] = nil end if k1 then t[k1] = v1 if k2 then t[k2] = v2 if k3 then t[k3] = v3 if k4 then t[k4] = v4 if k5 then t[k5] = v5 if k6 then t[k6] = v6 if k7 then t[k7] = v7 if k8 then t[k8] = v8 if k9 then t[k9] = v9 if k10 then t[k10] = v10 if k11 then t[k11] = v11 if k12 then t[k12] = v12 if k13 then t[k13] = v13 if k14 then t[k14] = v14 if k15 then t[k15] = v15 if k16 then t[k16] = v16 if k17 then t[k17] = v17 if k18 then t[k18] = v18 if k19 then t[k19] = v19 if k20 then t[k20] = v20 end end end end end end end end end end end end end end end end end end end end return t end local x = tmp2 function tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) t = {} tmp2 = x x = nil return tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) end end --local levels local buttons function lib:GetLibraryVersion() return MAJOR_VERSION, MINOR_VERSION end function lib:LibActivate(stub, oldLib, oldList) if oldLib and oldLib.registry then self.registry = oldLib.registry self.onceRegistered = oldLib.onceRegistered else self.registry = {} self.onceRegistered = {} local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") local oldX, oldY, clickTime WorldFrame:SetScript("OnMouseDown", function() oldX,oldY = GetCursorPosition() clickTime = GetTime() if WorldFrame_OnMouseDown then WorldFrame_OnMouseDown() end end) WorldFrame:SetScript("OnMouseUp", function() local x,y = GetCursorPosition() if not oldX or not oldY or not x or not y or not clickTime then self:Close() if WorldFrame_OnMouseUp then WorldFrame_OnMouseUp() end return end local d = math.abs(x - oldX) + math.abs(y - oldY) if d <= 5 and GetTime() - clickTime < 0.5 then self:Close() end if WorldFrame_OnMouseUp then WorldFrame_OnMouseUp() end end) local DropDownList1_Show = DropDownList1.Show function DropDownList1.Show(DropDownList1) if levels[1] and levels[1]:IsVisible() then self:Close() end DropDownList1_Show(DropDownList1) end local old_HideDropDownMenu = HideDropDownMenu function HideDropDownMenu(num) if levels[1] and levels[1]:IsVisible() then self:Close() end old_HideDropDownMenu(num) end local old_CloseDropDownMenus = CloseDropDownMenus function CloseDropDownMenus(num) if levels[1] and levels[1]:IsVisible() then self:Close() end old_CloseDropDownMenus(num) end end levels = {} buttons = {} end function lib:LibDeactivate(stub) levels = nil buttons = nil end local function StartCounting(self, levelNum) for i = levelNum, tgetn(levels) do if levels[i] then levels[i].count = 3 end end end local function StopCounting(self, level) for i = level, 1, -1 do if levels[i] then levels[i].count = nil end end end local function OnUpdate(self, arg1) for _,level in ipairs(levels) do if level.count then level.count = level.count - arg1 if level.count < 0 then level.count = nil self:Close(level.num) end end end end local function CheckSize(self, level) if not level.buttons then return end local height = 20 for _, button in ipairs(level.buttons) do height = height + button:GetHeight() end level:SetHeight(height) local width = 160 for _, button in ipairs(level.buttons) do local extra = 1 if button.hasArrow or button.hasColorSwatch then extra = extra + 16 end if not button.notCheckable then extra = extra + 24 end button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) if button.text:GetWidth() + extra > width then width = button.text:GetWidth() + extra end end level:SetWidth(width + 20) if level:GetLeft() and level:GetTop() and level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0 then level:ClearAllPoints() if level.lastDirection == "RIGHT" then if level.lastVDirection == "DOWN" then level:SetPoint("TOPLEFT", level.parent or level:GetParent(), "TOPRIGHT", 5, 10) else level:SetPoint("BOTTOMLEFT", level.parent or level:GetParent(), "BOTTOMRIGHT", 5, -10) end else if level.lastVDirection == "DOWN" then level:SetPoint("TOPRIGHT", level.parent or level:GetParent(), "TOPLEFT", -5, 10) else level:SetPoint("BOTTOMRIGHT", level.parent or level:GetParent(), "BOTTOMLEFT", -5, -10) end end end local dirty = false if not level:GetRight() then self:Close() return end if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then level.lastDirection = "LEFT" dirty = true elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then level.lastDirection = "RIGHT" dirty = true end if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then level.lastVDirection = "DOWN" dirty = true elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then level.lastVDirection = "UP" dirty = true end if dirty then level:ClearAllPoints() if level.lastDirection == "RIGHT" then if level.lastVDirection == "DOWN" then level:SetPoint("TOPLEFT", level.parent or level:GetParent(), "TOPRIGHT", 5, 10) else level:SetPoint("BOTTOMLEFT", level.parent or level:GetParent(), "BOTTOMRIGHT", 5, -10) end else if level.lastVDirection == "DOWN" then level:SetPoint("TOPRIGHT", level.parent or level:GetParent(), "TOPLEFT", -5, 10) else level:SetPoint("BOTTOMRIGHT", level.parent or level:GetParent(), "BOTTOMLEFT", -5, -10) end end end if level:GetTop() > GetScreenHeight() then local top = level:GetTop() local point, parent, relativePoint, x, y = level:GetPoint(1) level:ClearAllPoints() level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top) elseif level:GetBottom() < 0 then local bottom = level:GetBottom() local point, parent, relativePoint, x, y = level:GetPoint(1) level:ClearAllPoints() level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) end local left, bottom = level:GetLeft(), level:GetBottom() if mod(level.num, 5) == 0 then level:ClearAllPoints() level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) end end local Open local OpenSlider local Refresh local Clear local function ReleaseButton(self, level, index) if not level.buttons then return end if not level.buttons[index] then return end local button = level.buttons[index] button:Hide() if button.highlight then button.highlight:Hide() end tremove(level.buttons, index) tinsert(buttons, button) for k in pairs(button) do if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then button[k] = nil end end return true end local function Scroll(self, level, down) if down then if level:GetBottom() < 0 then local point, parent, relativePoint, x, y = level:GetPoint(1) level:SetPoint(point, parent, relativePoint, x, y + 50) if level:GetBottom() > 0 then level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom()) end end else if level:GetTop() > GetScreenHeight() then local point, parent, relativePoint, x, y = level:GetPoint(1) level:SetPoint(point, parent, relativePoint, x, y - 50) if level:GetTop() < GetScreenHeight() then level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop()) end end end end local sliderFrame local function AcquireButton(self, level) if not levels[level] then return end level = levels[level] if not level.buttons then level.buttons = {} end local button if tgetn(buttons) == 0 then button = CreateFrame("Button") button:SetFrameStrata("FULLSCREEN_DIALOG") button:SetHeight(16) local highlight = button:CreateTexture(nil, "BACKGROUND") highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") button.highlight = highlight highlight:SetBlendMode("ADD") highlight:SetAllPoints(button) highlight:Hide() local check = button:CreateTexture(nil, "ARTWORK") button.check = check check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") check:SetPoint("CENTER", button, "LEFT", 12, 0) check:SetWidth(24) check:SetHeight(24) local radioHighlight = button:CreateTexture(nil, "ARTWORK") button.radioHighlight = radioHighlight radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") radioHighlight:SetAllPoints(check) radioHighlight:SetBlendMode("ADD") radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) radioHighlight:Hide() button:SetScript("OnEnter", function() if sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1 then Refresh(self, this.level) return end self:Close(this.level.num + 1) if this.hasSlider then OpenSlider(self, this) elseif this.hasArrow then Open(self, this, nil, this.level.num + 1, this.value) end StopCounting(self, this.level.num + 1) if not this.disabled then highlight:Show() if this.isRadio then button.radioHighlight:Show() end end if this.tooltipTitle then GameTooltip_AddNewbieTip(this.tooltipTitle, 1.0, 1.0, 1.0, this.tooltipText, 1) end end) button:SetScript("OnLeave", function() highlight:Hide() button.radioHighlight:Hide() if this.level then StartCounting(self, this.level.num) end GameTooltip:Hide() end) button:SetScript("OnClick", function() if not this.disabled then if this.hasColorSwatch then local func = button.swatchFunc ColorPickerFrame.func = function() if func then func(ColorPickerFrame:GetColorRGB()) end end ColorPickerFrame.hasOpacity = this.hasOpacity local func = this.opacityFunc ColorPickerFrame.opacityFunc = function() if func then func(1 - OpacitySliderFrame:GetValue()) end end ColorPickerFrame.opacity = 1 - this.opacity ColorPickerFrame:SetColorRGB(this.r, this.g, this.b) if this.cancelFunc then local r, g, b, a = this.r, this.g, this.b, this.opacity local func = this.cancelFunc ColorPickerFrame.cancelFunc = function() func(r, g, b, a) end end self:Close(1) ShowUIPanel(ColorPickerFrame) elseif this.func then local level = button.level if type(this.func) == "string" then assert(type(this.arg1[this.func]) == "function", "Cannot call method " .. this.func) this.arg1[this.func](this.arg1, this.arg2, this.arg3) else this.func(this.arg1, this.arg2, this.arg3) end if this.closeWhenClicked then self:Close() elseif level:IsShown() then Refresh(self, level) end elseif this.closeWhenClicked then self:Close() end end end) local text = button:CreateFontString(nil, "ARTWORK") button.text = text text:SetFontObject(GameFontHighlightSmall) button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT) button:SetScript("OnMouseDown", function() if not this.disabled and (this.func or this.swatchFunc or this.closeWhenClicked) then text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1) end end) button:SetScript("OnMouseUp", function() if not this.disabled and (this.func or this.swatchFunc or this.closeWhenClicked) then text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 0 or 24, 0) end end) local arrow = button:CreateTexture(nil, "ARTWORK") button.arrow = arrow arrow:SetPoint("RIGHT", button, "RIGHT", 0, 0) arrow:SetWidth(16) arrow:SetHeight(16) arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") local colorSwatch = button:CreateTexture(nil, "OVERLAY") button.colorSwatch = colorSwatch colorSwatch:SetWidth(20) colorSwatch:SetHeight(20) colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") local texture = button:CreateTexture(nil, "OVERLAY") colorSwatch.texture = texture texture:SetTexture(1, 1, 1) texture:SetWidth(11.5) texture:SetHeight(11.5) texture:Show() texture:SetPoint("CENTER", colorSwatch, "CENTER") colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) else button = buttons[tgetn(buttons)] tremove(buttons, tgetn(buttons)) end button:SetParent(level) button:SetFrameStrata(level:GetFrameStrata()) button:SetFrameLevel(level:GetFrameLevel() + 1) button:SetPoint("LEFT", level, "LEFT", 10, 0) button:SetPoint("RIGHT", level, "RIGHT", -10, 0) if tgetn(level.buttons) == 0 then button:SetPoint("TOP", level, "TOP", 0, -10) else button:SetPoint("TOP", level.buttons[tgetn(level.buttons)], "BOTTOM", 0, 0) end button.text:SetPoint("LEFT", button, "LEFT", 24, 0) button:Show() button.level = level tinsert(level.buttons, button) if not level.parented then level.parented = true level:ClearAllPoints() if level.num == 1 then if level.parent ~= UIParent then level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") else level:SetPoint("CENTER", level.parent, "CENTER") end else if level.lastDirection == "RIGHT" then if level.lastVDirection == "DOWN" then level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) else level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10) end else if level.lastVDirection == "DOWN" then level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) else level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10) end end end level:SetFrameStrata("TOOLTIP") end return button end local function AcquireLevel(self, level) if not levels[level] then for i = tgetn(levels) + 1, level, -1 do local i = i local frame = CreateFrame("Button") if i == 1 then local old_CloseWindows = CloseWindows function CloseWindows(ignoreCenter) local found = old_CloseWindows(ignoreCenter) if levels[1]:IsShown() then self:Close() return 1 end return found end end levels[i] = frame frame.num = i frame:SetParent(UIParent) frame:SetFrameStrata("TOOLTIP") frame:Hide() frame:SetWidth(180) frame:SetHeight(10) frame:SetFrameLevel(i * 3) frame:SetScript("OnHide", function() self:Close(level + 1) end) frame:SetFrameStrata("FULLSCREEN_DIALOG") if frame.SetTopLevel then frame:SetTopLevel(true) end frame:EnableMouse(true) frame:EnableMouseWheel(true) local backdrop = CreateFrame("Frame", nil, frame) backdrop:SetAllPoints(frame) backdrop:SetBackdrop(tmp( 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", 'tile', true, 'insets', tmp2( 'left', 5, 'right', 5, 'top', 5, 'bottom', 5 ), 'tileSize', 16, 'edgeSize', 16 )) backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) frame:SetScript("OnClick", function() self:Close(i) end) frame:SetScript("OnEnter", function() StopCounting(self, i) end) frame:SetScript("OnLeave", function() StartCounting(self, i) end) frame:SetScript("OnMouseWheel", function() Scroll(self, frame, arg1 < 0) end) if i == 1 then frame:SetScript("OnUpdate", function() OnUpdate(self, arg1) end) levels[1].lastDirection = "RIGHT" levels[1].lastVDirection = "DOWN" else levels[i].lastDirection = levels[i - 1].lastDirection levels[i].lastVDirection = levels[i - 1].lastVDirection end end end return levels[level] end local baseFunc, currentLevel function Refresh(self, level) if type(level) == "number" then level = levels[level] end if not level then return end if baseFunc then currentLevel = level.num Clear(self, level) baseFunc(currentLevel, level.value, levels[level.num - 1] and levels[level.num - 1].value, levels[level.num - 2] and levels[level.num - 2].value, levels[level.num - 3] and levels[level.num - 3].value, levels[level.num - 4] and levels[level.num - 4].value) CheckSize(self, level) end end function lib:Refresh(level) Refresh(self, levels[level]) end function OpenSlider(self, parent) if not sliderFrame then sliderFrame = CreateFrame("Frame", nil, UIParent) sliderFrame:SetWidth(80) sliderFrame:SetHeight(170) sliderFrame:SetBackdrop(tmp( 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", 'tile', true, 'insets', tmp2( 'left', 5, 'right', 5, 'top', 5, 'bottom', 5 ), 'tileSize', 16, 'edgeSize', 16 )) sliderFrame:SetFrameStrata("TOOLTIP") if sliderFrame.SetTopLevel then sliderFrame:SetTopLevel(true) end sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) sliderFrame:EnableMouse(TRUE) sliderFrame:Hide() sliderFrame:SetPoint("CENTER", UIParent, "CENTER") local slider = CreateFrame("Slider", nil, sliderFrame) sliderFrame.slider = slider slider:SetOrientation("VERTICAL") slider:SetMinMaxValues(0, 1) slider:SetValueStep(0.01) slider:SetValue(0.5) slider:SetWidth(16) slider:SetHeight(128) slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) slider:SetBackdrop(tmp( 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", 'tile', true, 'edgeSize', 8, 'tileSize', 8, 'insets', tmp2( 'left', 3, 'right', 3, 'top', 3, 'bottom', 3 ) )) local texture = slider:CreateTexture() slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") local text = slider:CreateFontString(nil, "ARTWORK") sliderFrame.topText = text text:SetFontObject(GameFontGreenSmall) text:SetText("100%") text:SetPoint("BOTTOM", slider, "TOP") local text = slider:CreateFontString(nil, "ARTWORK") sliderFrame.bottomText = text text:SetFontObject(GameFontGreenSmall) text:SetText("0%") text:SetPoint("TOP", slider, "BOTTOM") local text = slider:CreateFontString(nil, "ARTWORK") sliderFrame.currentText = text text:SetFontObject(GameFontHighlightSmall) text:SetText("50%") text:SetPoint("LEFT", slider, "RIGHT") text:SetPoint("RIGHT", sliderFrame, "RIGHT", -6, 0) text:SetJustifyH("CENTER") local changed = false local inside = false slider:SetScript("OnValueChanged", function() if sliderFrame.changing then return end changed = true local done = false if sliderFrame.parent then if sliderFrame.parent.sliderFunc then local text = sliderFrame.parent.sliderFunc(1 - slider:GetValue()) if text then sliderFrame.currentText:SetText(text) done = true end end end if not done then sliderFrame.currentText:SetText(format("%.0f%%", (1 - slider:GetValue()) * 100)) end end) sliderFrame:SetScript("OnEnter", function() StopCounting(self, sliderFrame.level) end) sliderFrame:SetScript("OnLeave", function() StartCounting(self, sliderFrame.level) end) slider:SetScript("OnMouseDown", function() sliderFrame.mouseDown = true end) slider:SetScript("OnMouseUp", function() sliderFrame.mouseDown = false if changed and not inside then local parent = sliderFrame.parent Refresh(self, levels[sliderFrame.level - 1]) OpenSlider(self, parent) end end) slider:SetScript("OnEnter", function() inside = true StopCounting(self, sliderFrame.level) end) slider:SetScript("OnLeave", function() inside = false StartCounting(self, sliderFrame.level) if changed and not sliderFrame.mouseDown then local parent = sliderFrame.parent Refresh(self, levels[sliderFrame.level - 1]) OpenSlider(self, parent) end end) end sliderFrame.parent = parent sliderFrame.level = parent.level.num + 1 sliderFrame.parentValue = parent.level.value sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) sliderFrame.changing = true if not parent.sliderValue then parent.sliderValue = 0.5 end sliderFrame.slider:SetValue(1 - parent.sliderValue) sliderFrame.changing = false sliderFrame.bottomText:SetText(parent.sliderBottom or "0%") sliderFrame.topText:SetText(parent.sliderTop or "100%") local text if parent.sliderFunc then text = parent.sliderFunc(parent.sliderValue) end sliderFrame.currentText:SetText(text or format("%.0f%%", parent.sliderValue * 100)) local level = parent.level sliderFrame:Show() sliderFrame:ClearAllPoints() if level.lastDirection == "RIGHT" then if level.lastVDirection == "DOWN" then sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) else sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) end else if level.lastVDirection == "DOWN" then sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) else sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) end end local dirty if level.lastDirection == "RIGHT" then if sliderFrame:GetRight() > GetScreenWidth() then level.lastDirection = "LEFT" dirty = true end elseif sliderFrame:GetLeft() < 0 then level.lastDirection = "RIGHT" dirty = true end if level.lastVDirection == "DOWN" then if sliderFrame:GetBottom() < 0 then level.lastVDirection = "UP" dirty = true end elseif sliderFrame:GetTop() > GetScreenWidth() then level.lastVDirection = "DOWN" dirty = true end if dirty then sliderFrame:ClearAllPoints() if level.lastDirection == "RIGHT" then if level.lastVDirection == "DOWN" then sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) else sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) end else if level.lastVDirection == "DOWN" then sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) else sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) end end end local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() sliderFrame:ClearAllPoints() sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) if mod(level.num, 5) == 0 then local left, bottom = level:GetLeft(), level:GetBottom() level:ClearAllPoints() level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) end end function lib:IsOpen(parent) return levels[1] and levels[1]:IsShown() and (parent == levels[1].parent or parent == levels[1]:GetParent()) end function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY) self:Close(level) local frame = AcquireLevel(self, level) if level == 1 then frame.lastDirection = "RIGHT" frame.lastVDirection = "DOWN" else frame.lastDirection = levels[level - 1].lastDirection frame.lastVDirection = levels[level - 1].lastVDirection end frame:SetFrameStrata("TOOLTIP") frame:ClearAllPoints() frame.parent = parent frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) frame:Show() if level == 1 then baseFunc = func end levels[level].value = value relativePoint = relativePoint or point Refresh(self, levels[level]) if point then frame:ClearAllPoints() frame:SetPoint(point, parent, relativePoint) if cursorX then local left = frame:GetLeft() local width = frame:GetWidth() local curX, curY = GetCursorPosition() frame:ClearAllPoints() relativePoint = relativePoint or point if point == "BOTTOM" or point == "TOP" then if curX < GetScreenWidth() / 2 then point = point .. "LEFT" else point = point .. "RIGHT" end elseif point == "CENTER" then if curX < GetScreenWidth() / 2 then point = "LEFT" else point = "RIGHT" end end frame:SetPoint(point, parent, relativePoint, curX - left - width / 2, 0) if level == 1 then frame.lastDirection = "RIGHT" end elseif cursorY then local bottom = frame:GetBottom() local height = frame:GetHeight() local curX, curY = GetCursorPosition() frame:ClearAllPoints() relativePoint = relativePoint or point if point == "LEFT" or point == "RIGHT" then if curX < GetScreenHeight() / 2 then point = point .. "BOTTOM" else point = point .. "TOP" end elseif point == "CENTER" then if curX < GetScreenHeight() / 2 then point = "BOTTOM" else point = "TOP" end end frame:SetPoint(point, parent, relativePoint, 0, curY - bottom - height / 2) if level == 1 then frame.lastDirection = "DOWN" end end if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then if frame:GetBottom() < 0 then local point, parent, relativePoint, x, y = frame:GetPoint(1) local change = GetScreenHeight() - frame:GetTop() local otherChange = -frame:GetBottom() if otherChange < change then change = otherChange end frame:SetPoint(point, parent, relativePoint, x, y + change) elseif frame:GetTop() > GetScreenHeight() then local point, parent, relativePoint, x, y = frame:GetPoint(1) local change = GetScreenHeight() - frame:GetTop() local otherChange = -frame:GetBottom() if otherChange < change then change = otherChange end frame:SetPoint(point, parent, relativePoint, x, y + change) end end end StartCounting(self, level) end function lib:IsRegistered(parent) assert(parent, "You must provide a parent frame to check") return not not self.registry[parent] end function lib:Register(parent, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) assert(parent, "You must provide a parent frame to register with") if self.registry[parent] then self:Unregister(parent) end local info = new(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) self.registry[parent] = info if not info.dontHook and not self.onceRegistered[parent] then if parent:HasScript("OnMouseUp") then local script = parent:GetScript("OnMouseUp") parent:SetScript("OnMouseUp", function() if script then script() end if arg1 == "RightButton" and self.registry[parent] then if self:IsOpen(parent) then self:Close() else self:Open(parent) end end end) end if parent:HasScript("OnMouseDown") then local script = parent:GetScript("OnMouseDown") parent:SetScript("OnMouseDown", function() if script then script() end if self.registry[parent] then self:Close() end end) end end self.onceRegistered[parent] = true end function lib:Unregister(parent) assert(self.registry[parent], "You cannot unregister a parent frame if it has not been registered already.") self.registry[parent] = nil end function lib:Open(parent, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) local info if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then info = tmp() for k,v in pairs(self.registry[k1]) do info[k] = v end else info = tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) if self.registry[parent] then for k,v in pairs(self.registry[parent]) do if info[k] == nil then info[k] = v end end end end local point = info.point local relativePoint = info.relativePoint local cursorX = info.cursorX local cursorY = info.cursorY if type(point) == "function" then local b point, b = point(parent) if b then relativePoint = b end end if type(relativePoint) == "function" then relativePoint = relativePoint(parent) end Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) end function Clear(self, level) if level then if level.buttons then for i = tgetn(level.buttons), 1, -1 do ReleaseButton(self, level, i) end end end end function lib:Close(level) if DropDownList1:IsShown() then DropDownList1:Hide() end if not level then level = 1 end if level == 1 and levels[level] then levels[level].parented = false end if sliderFrame and sliderFrame.level == level then sliderFrame:Hide() end if levels[level] and levels[level]:IsShown() then Clear(self, levels[level]) levels[level]:Hide() end end function lib:AddLine(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) local info = tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) local level = info.level or currentLevel info.level = nil local button = AcquireButton(self, level) if not next(info) then info.disabled = true end button.disabled = info.isTitle or info.notClickable or info.disabled button.isTitle = info.isTitle button.notClickable = info.notClickable if button.isTitle then button.text:SetFontObject(GameFontNormalSmall) elseif button.notClickable then button.text:SetFontObject(GameFontHighlightSmall) elseif button.disabled then button.text:SetFontObject(GameFontDisableSmall) else button.text:SetFontObject(GameFontHighlightSmall) end if info.textR and info.textG and info.textB then button.textR = info.textR button.textG = info.textG button.textB = info.textB button.text:SetTextColor(button.textR, button.textG, button.textB) else button.text:SetTextColor(button.text:GetFontObject():GetTextColor()) end button.notCheckable = info.notCheckable button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0) button.checked = not info.notCheckable and info.checked button.isRadio = not info.notCheckable and info.isRadio if info.isRadio then button.check:Show() button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") if button.checked then button.check:SetTexCoord(0.25, 0.5, 0, 1) button.check:SetVertexColor(1, 1, 1, 1) else button.check:SetTexCoord(0, 0.25, 0, 1) button.check:SetVertexColor(1, 1, 1, 0.5) end button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") button.check:SetWidth(16) button.check:SetHeight(16) else if button.checked then button.check:SetTexCoord(0, 1, 0, 1) if info.checkIcon then button.check:SetWidth(16) button.check:SetHeight(16) button.check:SetTexture(info.checkIcon) else button.check:SetWidth(24) button.check:SetHeight(24) button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") end button.check:SetVertexColor(1, 1, 1, 1) else button.check:SetVertexColor(1, 1, 1, 0) end end if not button.disabled then button.func = info.func end button.hasColorSwatch = info.hasColorSwatch if button.hasColorSwatch then button.colorSwatch:Show() button.colorSwatch.texture:Show() button.r = info.r or 1 button.g = info.g or 1 button.b = info.b or 1 button.colorSwatch.texture:SetTexture(button.r, button.g, button.b) button.checked = false button.func = nil button.swatchFunc = info.swatchFunc button.hasOpacity = info.hasOpacity button.opacityFunc = info.opacityFunc button.opacity = info.opacity or 1 button.cancelFunc = info.cancelFunc else button.colorSwatch:Hide() button.colorSwatch.texture:Hide() end button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider) and info.hasArrow if button.hasArrow then button.arrow:SetAlpha(1) if info.hasSlider then button.hasSlider = info.hasSlider button.sliderTop = info.sliderTop or "100%" button.sliderBottom = info.sliderBottom or "0%" button.sliderFunc = info.sliderFunc button.sliderValue = info.sliderValue else button.value = info.value end else button.arrow:SetAlpha(0) end button.arg1 = info.arg1 button.arg2 = info.arg2 button.arg3 = info.arg3 button.closeWhenClicked = info.closeWhenClicked button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT local font,_ = button.text:GetFont() button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) button:SetHeight(button.textHeight + 6) button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT") button.text:SetJustifyH(info.justifyH or "LEFT") button.text:SetText(info.text) button.tooltipTitle = info.tooltipTitle button.tooltipText = info.tooltipText if type(button.func) == "string" then assert(type(button.arg1) == "table", "Cannot call method " .. button.func .. " on a non-table") assert(type(button.arg1[button.func]) == "function", "Method " .. button.func .. " nonexistant.") end end DewdropLib:Register(lib) lib = nil