flickerstreak@30: --[[ flickerstreak@30: Name: Dewdrop-2.0 flickerstreak@30: Revision: $Rev: 56529 $ flickerstreak@30: Author(s): ckknight (ckknight@gmail.com) flickerstreak@30: Website: http://ckknight.wowinterface.com/ flickerstreak@30: Documentation: http://wiki.wowace.com/index.php/Dewdrop-2.0 flickerstreak@30: SVN: http://svn.wowace.com/root/trunk/DewdropLib/Dewdrop-2.0 flickerstreak@30: Description: A library to provide a clean dropdown menu interface. flickerstreak@30: Dependencies: AceLibrary flickerstreak@30: License: LGPL v2.1 flickerstreak@30: ]] flickerstreak@30: flickerstreak@30: local MAJOR_VERSION = "Dewdrop-2.0" flickerstreak@30: local MINOR_VERSION = "$Revision: 56529 $" flickerstreak@30: flickerstreak@30: if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end flickerstreak@30: if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end flickerstreak@30: flickerstreak@30: local Dewdrop = {} flickerstreak@30: flickerstreak@30: local SharedMedia flickerstreak@30: flickerstreak@30: local CLOSE = "Close" flickerstreak@30: local CLOSE_DESC = "Close the menu." flickerstreak@30: local VALIDATION_ERROR = "Validation error." flickerstreak@30: local USAGE_TOOLTIP = "Usage: %s." flickerstreak@30: local RANGE_TOOLTIP = "Note that you can scroll your mouse wheel while over the slider to step by one." flickerstreak@30: local RESET_KEYBINDING_DESC = "Hit escape to clear the keybinding." flickerstreak@30: local KEY_BUTTON1 = "Left Mouse" flickerstreak@30: local KEY_BUTTON2 = "Right Mouse" flickerstreak@30: local DISABLED = "Disabled" flickerstreak@30: local DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" flickerstreak@30: flickerstreak@30: if GetLocale() == "deDE" then flickerstreak@30: CLOSE = "Schlie\195\159en" flickerstreak@30: CLOSE_DESC = "Men\195\188 schlie\195\159en." flickerstreak@30: VALIDATION_ERROR = "Validierungsfehler." flickerstreak@30: USAGE_TOOLTIP = "Benutzung: %s." flickerstreak@30: RANGE_TOOLTIP = "Beachte das du mit dem Mausrad scrollen kannst solange du mit dem Mauszeiger \195\188ber dem Schieberegler bist, um feinere Spr\195\188nge zu machen." flickerstreak@30: RESET_KEYBINDING_DESC = "Escape dr\195\188cken, um die Tastenbelegung zu l\195\182schen." flickerstreak@30: KEY_BUTTON1 = "Linke Maustaste" flickerstreak@30: KEY_BUTTON2 = "Rechte Maustaste" flickerstreak@30: DISABLED = "Deaktiviert" flickerstreak@30: DEFAULT_CONFIRM_MESSAGE = "Bist du sicher das du `%s' machen willst?" flickerstreak@30: elseif GetLocale() == "koKR" then flickerstreak@30: CLOSE = "닫기" flickerstreak@30: CLOSE_DESC = "메뉴를 닫습니다." flickerstreak@30: VALIDATION_ERROR = "오류 확인." flickerstreak@30: USAGE_TOOLTIP = "사용법: %s." flickerstreak@30: RANGE_TOOLTIP = "알림 : 슬라이더 위에서 마우스 휠을 사용하면 한단계씩 조절할 수 있습니다." flickerstreak@30: RESET_KEYBINDING_DESC = "단축키를 해제하려면 ESC키를 누르세요." flickerstreak@30: KEY_BUTTON1 = "왼쪽 마우스" flickerstreak@30: KEY_BUTTON2 = "오른쪽 마우스" flickerstreak@30: DISABLED = "비활성화됨" flickerstreak@30: DEFAULT_CONFIRM_MESSAGE = "정말로 `%s' 실행을 하시겠습니까 ?" flickerstreak@30: elseif GetLocale() == "frFR" then flickerstreak@30: CLOSE = "Fermer" flickerstreak@30: CLOSE_DESC = "Ferme le menu." flickerstreak@30: VALIDATION_ERROR = "Erreur de validation." flickerstreak@30: USAGE_TOOLTIP = "Utilisation : %s." flickerstreak@30: RANGE_TOOLTIP = "Vous pouvez aussi utiliser la molette de la souris pour pour modifier progressivement." flickerstreak@30: RESET_KEYBINDING_DESC = "Appuyez sur la touche Echappement pour effacer le raccourci." flickerstreak@30: KEY_BUTTON1 = "Clic gauche" flickerstreak@30: KEY_BUTTON2 = "Clic droit" flickerstreak@30: DISABLED = "D\195\169sactiv\195\169" flickerstreak@30: DEFAULT_CONFIRM_MESSAGE = "\195\138tes-vous s\195\187r de vouloir effectuer '%s' ?" flickerstreak@30: elseif GetLocale() == "esES" then flickerstreak@30: CLOSE = "Cerrar" flickerstreak@30: CLOSE_DESC = "Cierra el menú." flickerstreak@30: VALIDATION_ERROR = "Error de validación." flickerstreak@30: USAGE_TOOLTIP = "Uso: %s." flickerstreak@30: RANGE_TOOLTIP = "Puedes desplazarte verticalmente con la rueda del ratón sobre el desplazador." flickerstreak@30: RESET_KEYBINDING_DESC = "Pulsa Escape para borrar la asignación de tecla." flickerstreak@30: KEY_BUTTON1 = "Clic Izquierdo" flickerstreak@30: KEY_BUTTON2 = "Clic Derecho" flickerstreak@30: DISABLED = "Desactivado" flickerstreak@30: DEFAULT_CONFIRM_MESSAGE = "¿Estás seguro de querer realizar `%s'?" flickerstreak@30: elseif GetLocale() == "zhTW" then flickerstreak@30: CLOSE = "關閉" flickerstreak@30: CLOSE_DESC = "關閉選單。" flickerstreak@30: VALIDATION_ERROR = "驗證錯誤。" flickerstreak@30: USAGE_TOOLTIP = "用法: %s。" flickerstreak@30: RANGE_TOOLTIP = "你可以在捲動條上使用滑鼠滾輪來捲動。" flickerstreak@30: RESET_KEYBINDING_DESC = "按Esc鍵清除快捷鍵。" flickerstreak@30: KEY_BUTTON1 = "滑鼠左鍵" flickerstreak@30: KEY_BUTTON2 = "滑鼠右鍵" flickerstreak@30: DISABLED = "停用" flickerstreak@30: DEFAULT_CONFIRM_MESSAGE = "是否執行「%s」?" flickerstreak@30: elseif GetLocale() == "zhCN" then flickerstreak@30: CLOSE = "关闭" flickerstreak@30: CLOSE_DESC = "关闭菜单" flickerstreak@30: VALIDATION_ERROR = "验证错误." flickerstreak@30: USAGE_TOOLTIP = "用法: %s." flickerstreak@30: RANGE_TOOLTIP = "你可以在滚动条上使用鼠标滚轮来翻页." flickerstreak@30: RESET_KEYBINDING_DESC = "按ESC键清除按键绑定" flickerstreak@30: KEY_BUTTON1 = "鼠标左键" flickerstreak@30: KEY_BUTTON2 = "鼠标右键" flickerstreak@30: DISABLED = "禁用" flickerstreak@30: DEFAULT_CONFIRM_MESSAGE = "是否执行'%s'?" flickerstreak@30: end flickerstreak@30: flickerstreak@30: Dewdrop.KEY_BUTTON1 = KEY_BUTTON1 flickerstreak@30: Dewdrop.KEY_BUTTON2 = KEY_BUTTON2 flickerstreak@30: flickerstreak@30: local function new(...) flickerstreak@30: local t = {} flickerstreak@30: for i = 1, select('#', ...), 2 do flickerstreak@30: local k = select(i, ...) flickerstreak@30: if k then flickerstreak@30: t[k] = select(i+1, ...) flickerstreak@30: else flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: return t flickerstreak@30: end flickerstreak@30: flickerstreak@30: local tmp flickerstreak@30: do flickerstreak@30: local t = {} flickerstreak@30: function tmp(...) flickerstreak@30: for k in pairs(t) do flickerstreak@30: t[k] = nil flickerstreak@30: end flickerstreak@30: for i = 1, select('#', ...), 2 do flickerstreak@30: local k = select(i, ...) flickerstreak@30: if k then flickerstreak@30: t[k] = select(i+1, ...) flickerstreak@30: else flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: return t flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local tmp2 flickerstreak@30: do flickerstreak@30: local t = {} flickerstreak@30: function tmp2(...) flickerstreak@30: for k in pairs(t) do flickerstreak@30: t[k] = nil flickerstreak@30: end flickerstreak@30: for i = 1, select('#', ...), 2 do flickerstreak@30: local k = select(i, ...) flickerstreak@30: if k then flickerstreak@30: t[k] = select(i+1, ...) flickerstreak@30: else flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: return t flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local levels flickerstreak@30: local buttons flickerstreak@30: flickerstreak@30: flickerstreak@30: -- Secure frame handling: flickerstreak@30: -- Rather than using secure buttons in the menu (has problems), we have one flickerstreak@30: -- master secureframe that we pop onto menu items on mouseover. This requires flickerstreak@30: -- some dark magic with OnLeave etc, but it's not too bad. flickerstreak@30: flickerstreak@30: local secureFrame = CreateFrame("Button", nil, nil, "SecureActionButtonTemplate") flickerstreak@30: secureFrame:Hide() flickerstreak@30: flickerstreak@30: local function secureFrame_Show(self) flickerstreak@30: local owner = self.owner flickerstreak@30: flickerstreak@30: if self.secure then -- Leftovers from previos owner, clean up! ("Shouldn't" happen but does..) flickerstreak@30: for k,v in pairs(self.secure) do flickerstreak@30: self:SetAttribute(k, nil) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self.secure = owner.secure; -- Grab hold of new secure data flickerstreak@30: flickerstreak@30: local scale = owner:GetEffectiveScale() flickerstreak@30: flickerstreak@30: self:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", owner:GetLeft() * scale, owner:GetTop() * scale) flickerstreak@30: self:SetPoint("BOTTOMRIGHT", nil, "BOTTOMLEFT", owner:GetRight() * scale, owner:GetBottom() * scale) flickerstreak@30: self:EnableMouse(true) flickerstreak@30: for k,v in pairs(self.secure) do flickerstreak@30: self:SetAttribute(k, v) flickerstreak@30: end flickerstreak@30: flickerstreak@30: secureFrame:SetFrameStrata(owner:GetFrameStrata()) flickerstreak@30: secureFrame:SetFrameLevel(owner:GetFrameLevel()+1) flickerstreak@30: flickerstreak@30: self:Show() flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function secureFrame_Hide(self) flickerstreak@30: self:Hide() flickerstreak@30: if self.secure then flickerstreak@30: for k,v in pairs(self.secure) do flickerstreak@30: self:SetAttribute(k, nil) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self.secure = nil flickerstreak@30: end flickerstreak@30: flickerstreak@30: secureFrame:SetScript("OnEvent", flickerstreak@30: function() flickerstreak@30: if event=="PLAYER_REGEN_ENABLED" then flickerstreak@30: this.combat = false flickerstreak@30: if not this:IsShown() and this.owner then flickerstreak@30: secureFrame_Show(this) flickerstreak@30: end flickerstreak@30: elseif event=="PLAYER_REGEN_DISABLED" then flickerstreak@30: this.combat = true flickerstreak@30: if this:IsShown() then flickerstreak@30: secureFrame_Hide(this) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: ) flickerstreak@30: secureFrame:RegisterEvent("PLAYER_REGEN_ENABLED") flickerstreak@30: secureFrame:RegisterEvent("PLAYER_REGEN_DISABLED") flickerstreak@30: flickerstreak@30: secureFrame:SetScript("OnLeave", flickerstreak@30: function() flickerstreak@30: local owner=this.owner flickerstreak@30: this:Deactivate() flickerstreak@30: owner:GetScript("OnLeave")() flickerstreak@30: end flickerstreak@30: ) flickerstreak@30: flickerstreak@30: secureFrame:HookScript("OnClick", flickerstreak@30: function() flickerstreak@30: local realthis = this flickerstreak@30: this = this.owner flickerstreak@30: this:GetScript("OnClick")() flickerstreak@30: end flickerstreak@30: ) flickerstreak@30: flickerstreak@30: function secureFrame:IsOwnedBy(frame) flickerstreak@30: return self.owner == frame flickerstreak@30: end flickerstreak@30: flickerstreak@30: function secureFrame:Activate(owner) flickerstreak@30: if self.owner then -- "Shouldn't" happen but apparently it does and I cba to troubleshoot... flickerstreak@30: if not self.combat then flickerstreak@30: secureFrame_Hide(self) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self.owner = owner flickerstreak@30: if not self.combat then flickerstreak@30: secureFrame_Show(self) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: function secureFrame:Deactivate() flickerstreak@30: if not self.combat then flickerstreak@30: secureFrame_Hide(self) flickerstreak@30: end flickerstreak@30: self.owner = nil flickerstreak@30: end flickerstreak@30: flickerstreak@30: -- END secure frame utilities flickerstreak@30: flickerstreak@30: flickerstreak@30: -- Underline on mouseover - use a single global underline that we move around, no point in creating lots of copies flickerstreak@30: local underlineFrame = CreateFrame("Frame", nil) flickerstreak@30: underlineFrame.tx = underlineFrame:CreateTexture() flickerstreak@30: underlineFrame.tx:SetTexture(1,1,0.5,0.75) flickerstreak@30: underlineFrame:SetScript("OnHide", function(this) this:Hide(); end) flickerstreak@30: underlineFrame:SetScript("OnShow", function(this) -- change sizing on the fly to catch runtime uiscale changes flickerstreak@30: underlineFrame.tx:SetPoint("TOPLEFT", -1, -2/this:GetEffectiveScale()) flickerstreak@30: underlineFrame.tx:SetPoint("RIGHT", 1,0) flickerstreak@30: underlineFrame.tx:SetHeight(0.6 / this:GetEffectiveScale()); flickerstreak@30: end) flickerstreak@30: underlineFrame:SetHeight(1) flickerstreak@30: flickerstreak@30: -- END underline on mouseover flickerstreak@30: flickerstreak@30: flickerstreak@30: local function GetScaledCursorPosition() flickerstreak@30: local x, y = GetCursorPosition() flickerstreak@30: local scale = UIParent:GetEffectiveScale() flickerstreak@30: return x / scale, y / scale flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function StartCounting(self, level) flickerstreak@30: for i = level, 1, -1 do flickerstreak@30: if levels[i] then flickerstreak@30: levels[i].count = 3 flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function StopCounting(self, level) flickerstreak@30: for i = level, 1, -1 do flickerstreak@30: if levels[i] then flickerstreak@30: levels[i].count = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function OnUpdate(self, elapsed) flickerstreak@30: for _,level in ipairs(levels) do flickerstreak@30: local count = level.count flickerstreak@30: if count then flickerstreak@30: count = count - elapsed flickerstreak@30: if count < 0 then flickerstreak@30: level.count = nil flickerstreak@30: self:Close(level.num) flickerstreak@30: else flickerstreak@30: level.count = count flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function CheckDualMonitor(self, frame) flickerstreak@30: local ratio = GetScreenWidth() / GetScreenHeight() flickerstreak@30: if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then flickerstreak@30: local offsetx flickerstreak@30: if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then flickerstreak@30: offsetx = GetScreenWidth() / 2 - frame:GetRight() flickerstreak@30: else flickerstreak@30: offsetx = GetScreenWidth() / 2 - frame:GetLeft() flickerstreak@30: end flickerstreak@30: local point, parent, relativePoint, x, y = frame:GetPoint(1) flickerstreak@30: frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function CheckSize(self, level) flickerstreak@30: if not level.buttons then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: local height = 20 flickerstreak@30: for _, button in ipairs(level.buttons) do flickerstreak@30: height = height + button:GetHeight() flickerstreak@30: end flickerstreak@30: level:SetHeight(height) flickerstreak@30: local width = 160 flickerstreak@30: for _, button in ipairs(level.buttons) do flickerstreak@30: local extra = 1 flickerstreak@30: if button.hasArrow or button.hasColorSwatch then flickerstreak@30: extra = extra + 16 flickerstreak@30: end flickerstreak@30: if not button.notCheckable then flickerstreak@30: extra = extra + 24 flickerstreak@30: end flickerstreak@30: button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) flickerstreak@30: if button.text:GetWidth() + extra > width then flickerstreak@30: width = button.text:GetWidth() + extra flickerstreak@30: end flickerstreak@30: end flickerstreak@30: level:SetWidth(width + 20) flickerstreak@30: if level:GetLeft() and level:GetRight() and level:GetTop() and level:GetBottom() and (level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0) then flickerstreak@30: level:ClearAllPoints() flickerstreak@30: local parent = level.parent or level:GetParent() flickerstreak@30: if type(parent) ~= "table" then flickerstreak@30: parent = UIParent flickerstreak@30: end flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local dirty = false flickerstreak@30: if not level:GetRight() then flickerstreak@30: self:Close() flickerstreak@30: return flickerstreak@30: end flickerstreak@30: if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then flickerstreak@30: level.lastDirection = "LEFT" flickerstreak@30: dirty = true flickerstreak@30: elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then flickerstreak@30: level.lastDirection = "RIGHT" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then flickerstreak@30: level.lastVDirection = "DOWN" flickerstreak@30: dirty = true flickerstreak@30: elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then flickerstreak@30: level.lastVDirection = "UP" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: if dirty then flickerstreak@30: level:ClearAllPoints() flickerstreak@30: local parent = level.parent or level:GetParent() flickerstreak@30: if type(parent) ~= "table" then flickerstreak@30: parent = UIParent flickerstreak@30: end flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if level:GetTop() > GetScreenHeight() then flickerstreak@30: local top = level:GetTop() flickerstreak@30: local point, parent, relativePoint, x, y = level:GetPoint(1) flickerstreak@30: level:ClearAllPoints() flickerstreak@30: level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top) flickerstreak@30: elseif level:GetBottom() < 0 then flickerstreak@30: local bottom = level:GetBottom() flickerstreak@30: local point, parent, relativePoint, x, y = level:GetPoint(1) flickerstreak@30: level:ClearAllPoints() flickerstreak@30: level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) flickerstreak@30: end flickerstreak@30: CheckDualMonitor(self, level) flickerstreak@30: if mod(level.num, 5) == 0 then flickerstreak@30: local left, bottom = level:GetLeft(), level:GetBottom() flickerstreak@30: level:ClearAllPoints() flickerstreak@30: level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local Open flickerstreak@30: local OpenSlider flickerstreak@30: local OpenEditBox flickerstreak@30: local Refresh flickerstreak@30: local Clear flickerstreak@30: local function ReleaseButton(self, level, index) flickerstreak@30: if not level.buttons then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: if not level.buttons[index] then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: local button = level.buttons[index] flickerstreak@30: button:Hide() flickerstreak@30: if button.highlight then flickerstreak@30: button.highlight:Hide() flickerstreak@30: end flickerstreak@30: -- button.arrow:SetVertexColor(1, 1, 1) flickerstreak@30: -- button.arrow:SetHeight(16) flickerstreak@30: -- button.arrow:SetWidth(16) flickerstreak@30: table.remove(level.buttons, index) flickerstreak@30: table.insert(buttons, button) flickerstreak@30: for k in pairs(button) do flickerstreak@30: if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then flickerstreak@30: button[k] = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: return true flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function Scroll(self, level, down) flickerstreak@30: if down then flickerstreak@30: if level:GetBottom() < 0 then flickerstreak@30: local point, parent, relativePoint, x, y = level:GetPoint(1) flickerstreak@30: level:SetPoint(point, parent, relativePoint, x, y + 50) flickerstreak@30: if level:GetBottom() > 0 then flickerstreak@30: level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom()) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level:GetTop() > GetScreenHeight() then flickerstreak@30: local point, parent, relativePoint, x, y = level:GetPoint(1) flickerstreak@30: level:SetPoint(point, parent, relativePoint, x, y - 50) flickerstreak@30: if level:GetTop() < GetScreenHeight() then flickerstreak@30: level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop()) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function getArgs(t, str, num, ...) flickerstreak@30: local x = t[str .. num] flickerstreak@30: if x == nil then flickerstreak@30: return ... flickerstreak@30: else flickerstreak@30: return x, getArgs(t, str, num + 1, ...) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local sliderFrame flickerstreak@30: local editBoxFrame flickerstreak@30: flickerstreak@30: local normalFont flickerstreak@30: local lastSetFont flickerstreak@30: local justSetFont = false flickerstreak@30: local regionTmp = {} flickerstreak@30: local function fillRegionTmp(...) flickerstreak@30: for i = 1, select('#', ...) do flickerstreak@30: regionTmp[i] = select(i, ...) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function showGameTooltip(this) flickerstreak@30: if this.tooltipTitle or this.tooltipText then flickerstreak@30: GameTooltip_SetDefaultAnchor(GameTooltip, this) flickerstreak@30: local disabled = not this.isTitle and this.disabled flickerstreak@30: local font flickerstreak@30: if this.tooltipTitle then flickerstreak@30: if SharedMedia and SharedMedia:IsValid("font", this.tooltipTitle) then flickerstreak@30: font = SharedMedia:Fetch("font", this.tooltipTitle) flickerstreak@30: end flickerstreak@30: if disabled then flickerstreak@30: GameTooltip:SetText(this.tooltipTitle, 0.5, 0.5, 0.5, 1) flickerstreak@30: else flickerstreak@30: GameTooltip:SetText(this.tooltipTitle, 1, 1, 1, 1) flickerstreak@30: end flickerstreak@30: if this.tooltipText then flickerstreak@30: if not font and SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then flickerstreak@30: font = SharedMedia:Fetch("font", this.tooltipText) flickerstreak@30: end flickerstreak@30: if disabled then flickerstreak@30: GameTooltip:AddLine(this.tooltipText, (NORMAL_FONT_COLOR.r + 0.5) / 2, (NORMAL_FONT_COLOR.g + 0.5) / 2, (NORMAL_FONT_COLOR.b + 0.5) / 2, 1) flickerstreak@30: else flickerstreak@30: GameTooltip:AddLine(this.tooltipText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then flickerstreak@30: font = SharedMedia:Fetch("font", this.tooltipText) flickerstreak@30: end flickerstreak@30: if disabled then flickerstreak@30: GameTooltip:SetText(this.tooltipText, 0.5, 0.5, 0.5, 1) flickerstreak@30: else flickerstreak@30: GameTooltip:SetText(this.tooltipText, 1, 1, 1, 1) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if font then flickerstreak@30: fillRegionTmp(GameTooltip:GetRegions()) flickerstreak@30: lastSetFont = font flickerstreak@30: justSetFont = true flickerstreak@30: for i,v in ipairs(regionTmp) do flickerstreak@30: if v.SetFont then flickerstreak@30: local norm,size,outline = v:GetFont() flickerstreak@30: v:SetFont(font, size, outline) flickerstreak@30: if not normalFont then flickerstreak@30: normalFont = norm flickerstreak@30: end flickerstreak@30: end flickerstreak@30: regionTmp[i] = nil flickerstreak@30: end flickerstreak@30: elseif not normalFont then flickerstreak@30: fillRegionTmp(GameTooltip:GetRegions()) flickerstreak@30: for i,v in ipairs(regionTmp) do flickerstreak@30: if v.GetFont and not normalFont then flickerstreak@30: normalFont = v:GetFont() flickerstreak@30: end flickerstreak@30: regionTmp[i] = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: GameTooltip:Show() flickerstreak@30: end flickerstreak@30: if this.tooltipFunc then flickerstreak@30: GameTooltip:SetOwner(this, "ANCHOR_NONE") flickerstreak@30: GameTooltip:SetPoint("TOPLEFT", this, "TOPRIGHT", 5, 0) flickerstreak@30: this.tooltipFunc(getArgs(this, 'tooltipArg', 1)) flickerstreak@30: GameTooltip:Show() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local tmpt = setmetatable({}, {mode='v'}) flickerstreak@30: local numButtons = 0 flickerstreak@30: local function AcquireButton(self, level) flickerstreak@30: if not levels[level] then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: level = levels[level] flickerstreak@30: if not level.buttons then flickerstreak@30: level.buttons = {} flickerstreak@30: end flickerstreak@30: local button flickerstreak@30: if #buttons == 0 then flickerstreak@30: numButtons = numButtons + 1 flickerstreak@30: button = CreateFrame("Button", "Dewdrop20Button" .. numButtons, nil) flickerstreak@30: button:SetFrameStrata("FULLSCREEN_DIALOG") flickerstreak@30: button:SetHeight(16) flickerstreak@30: local highlight = button:CreateTexture(nil, "BACKGROUND") flickerstreak@30: highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") flickerstreak@30: button.highlight = highlight flickerstreak@30: highlight:SetBlendMode("ADD") flickerstreak@30: highlight:SetAllPoints(button) flickerstreak@30: highlight:Hide() flickerstreak@30: local check = button:CreateTexture(nil, "ARTWORK") flickerstreak@30: button.check = check flickerstreak@30: check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") flickerstreak@30: check:SetPoint("CENTER", button, "LEFT", 12, 0) flickerstreak@30: check:SetWidth(24) flickerstreak@30: check:SetHeight(24) flickerstreak@30: local radioHighlight = button:CreateTexture(nil, "ARTWORK") flickerstreak@30: button.radioHighlight = radioHighlight flickerstreak@30: radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") flickerstreak@30: radioHighlight:SetAllPoints(check) flickerstreak@30: radioHighlight:SetBlendMode("ADD") flickerstreak@30: radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) flickerstreak@30: radioHighlight:Hide() flickerstreak@30: button:SetScript("OnEnter", function() flickerstreak@30: if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1) or (editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == this.level.num + 1) then flickerstreak@30: for i = 1, this.level.num do flickerstreak@30: Refresh(self, levels[i]) flickerstreak@30: end flickerstreak@30: return flickerstreak@30: end flickerstreak@30: self:Close(this.level.num + 1) flickerstreak@30: if not this.disabled then flickerstreak@30: if this.secure then flickerstreak@30: secureFrame:Activate(this) flickerstreak@30: elseif this.hasSlider then flickerstreak@30: OpenSlider(self, this) flickerstreak@30: elseif this.hasEditBox then flickerstreak@30: OpenEditBox(self, this) flickerstreak@30: elseif this.hasArrow then flickerstreak@30: Open(self, this, nil, this.level.num + 1, this.value) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if not this.level then -- button reclaimed flickerstreak@30: return flickerstreak@30: end flickerstreak@30: StopCounting(self, this.level.num + 1) flickerstreak@30: if not this.disabled then flickerstreak@30: highlight:Show() flickerstreak@30: if this.isRadio then flickerstreak@30: button.radioHighlight:Show() flickerstreak@30: end flickerstreak@30: if this.mouseoverUnderline then flickerstreak@30: underlineFrame:SetParent(this) flickerstreak@30: underlineFrame:SetPoint("BOTTOMLEFT",this.text,0,0) flickerstreak@30: underlineFrame:SetWidth(this.text:GetWidth()) flickerstreak@30: underlineFrame:Show() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: showGameTooltip(this) flickerstreak@30: end) flickerstreak@30: button:SetScript("OnHide", function() flickerstreak@30: if this.secure and secureFrame:IsOwnedBy(this) then flickerstreak@30: secureFrame:Deactivate() flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: button:SetScript("OnLeave", function() flickerstreak@30: if this.secure and secureFrame:IsShown() then flickerstreak@30: return; -- it's ok, we didn't actually mouse out of the button, only onto the secure frame on top of it flickerstreak@30: end flickerstreak@30: underlineFrame:Hide() flickerstreak@30: if not this.selected then flickerstreak@30: highlight:Hide() flickerstreak@30: end flickerstreak@30: button.radioHighlight:Hide() flickerstreak@30: if this.level then flickerstreak@30: StartCounting(self, this.level.num) flickerstreak@30: end flickerstreak@30: GameTooltip:Hide() flickerstreak@30: end) flickerstreak@30: local first = true flickerstreak@30: button:SetScript("OnClick", function() flickerstreak@30: if not this.disabled then flickerstreak@30: if this.hasColorSwatch then flickerstreak@30: local func = button.colorFunc flickerstreak@30: local hasOpacity = this.hasOpacity flickerstreak@30: local this = this flickerstreak@30: for k in pairs(tmpt) do flickerstreak@30: tmpt[k] = nil flickerstreak@30: end flickerstreak@30: for i = 1, 1000 do flickerstreak@30: local x = this['colorArg'..i] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: else flickerstreak@30: tmpt[i] = x flickerstreak@30: end flickerstreak@30: end flickerstreak@30: ColorPickerFrame.func = function() flickerstreak@30: if func then flickerstreak@30: local r,g,b = ColorPickerFrame:GetColorRGB() flickerstreak@30: local a = hasOpacity and 1 - OpacitySliderFrame:GetValue() or nil flickerstreak@30: local n = #tmpt flickerstreak@30: tmpt[n+1] = r flickerstreak@30: tmpt[n+2] = g flickerstreak@30: tmpt[n+3] = b flickerstreak@30: tmpt[n+4] = a flickerstreak@30: func(unpack(tmpt)) flickerstreak@30: tmpt[n+1] = nil flickerstreak@30: tmpt[n+2] = nil flickerstreak@30: tmpt[n+3] = nil flickerstreak@30: tmpt[n+4] = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: ColorPickerFrame.hasOpacity = this.hasOpacity flickerstreak@30: ColorPickerFrame.opacityFunc = ColorPickerFrame.func flickerstreak@30: ColorPickerFrame.opacity = 1 - this.opacity flickerstreak@30: ColorPickerFrame:SetColorRGB(this.r, this.g, this.b) flickerstreak@30: local r, g, b, a = this.r, this.g, this.b, this.opacity flickerstreak@30: ColorPickerFrame.cancelFunc = function() flickerstreak@30: if func then flickerstreak@30: local n = #tmpt flickerstreak@30: tmpt[n+1] = r flickerstreak@30: tmpt[n+2] = g flickerstreak@30: tmpt[n+3] = b flickerstreak@30: tmpt[n+4] = a flickerstreak@30: func(unpack(tmpt)) flickerstreak@30: for i = 1, n+4 do flickerstreak@30: tmpt[i] = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self:Close(1) flickerstreak@30: ShowUIPanel(ColorPickerFrame) flickerstreak@30: elseif this.func then flickerstreak@30: local level = this.level flickerstreak@30: if type(this.func) == "string" then flickerstreak@30: if type(this.arg1[this.func]) ~= "function" then flickerstreak@30: self:error("Cannot call method %q", this.func) flickerstreak@30: end flickerstreak@30: this.arg1[this.func](this.arg1, getArgs(this, 'arg', 2)) flickerstreak@30: else flickerstreak@30: this.func(getArgs(this, 'arg', 1)) flickerstreak@30: end flickerstreak@30: if this.closeWhenClicked then flickerstreak@30: self:Close() flickerstreak@30: elseif level:IsShown() then flickerstreak@30: for i = 1, level.num do flickerstreak@30: Refresh(self, levels[i]) flickerstreak@30: end flickerstreak@30: local value = levels[level.num].value flickerstreak@30: for i = level.num-1, 1, -1 do flickerstreak@30: local level = levels[i] flickerstreak@30: local good = false flickerstreak@30: for _,button in ipairs(level.buttons) do flickerstreak@30: if button.value == value then flickerstreak@30: good = true flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if not good then flickerstreak@30: Dewdrop:Close(i+1) flickerstreak@30: end flickerstreak@30: value = levels[i].value flickerstreak@30: end flickerstreak@30: end flickerstreak@30: elseif this.closeWhenClicked then flickerstreak@30: self:Close() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: local text = button:CreateFontString(nil, "ARTWORK") flickerstreak@30: button.text = text flickerstreak@30: text:SetFontObject(GameFontHighlightSmall) flickerstreak@30: button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT) flickerstreak@30: button:SetScript("OnMouseDown", function() flickerstreak@30: if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then flickerstreak@30: text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1) flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: button:SetScript("OnMouseUp", function() flickerstreak@30: if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then flickerstreak@30: text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 0 or 24, 0) flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: local arrow = button:CreateTexture(nil, "ARTWORK") flickerstreak@30: button.arrow = arrow flickerstreak@30: arrow:SetPoint("LEFT", button, "RIGHT", -16, 0) flickerstreak@30: arrow:SetWidth(16) flickerstreak@30: arrow:SetHeight(16) flickerstreak@30: arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") flickerstreak@30: local colorSwatch = button:CreateTexture(nil, "ARTWORK") flickerstreak@30: button.colorSwatch = colorSwatch flickerstreak@30: colorSwatch:SetWidth(20) flickerstreak@30: colorSwatch:SetHeight(20) flickerstreak@30: colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") flickerstreak@30: local texture = button:CreateTexture(nil, "OVERLAY") flickerstreak@30: colorSwatch.texture = texture flickerstreak@30: texture:SetTexture("Interface\\Buttons\\WHITE8X8") flickerstreak@30: texture:SetWidth(11.5) flickerstreak@30: texture:SetHeight(11.5) flickerstreak@30: texture:Show() flickerstreak@30: texture:SetPoint("CENTER", colorSwatch, "CENTER") flickerstreak@30: colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) flickerstreak@30: else flickerstreak@30: button = table.remove(buttons) flickerstreak@30: end flickerstreak@30: button:ClearAllPoints() flickerstreak@30: button:SetParent(level) flickerstreak@30: button:SetFrameStrata(level:GetFrameStrata()) flickerstreak@30: button:SetFrameLevel(level:GetFrameLevel() + 1) flickerstreak@30: button:SetPoint("LEFT", level, "LEFT", 10, 0) flickerstreak@30: button:SetPoint("RIGHT", level, "RIGHT", -10, 0) flickerstreak@30: if #level.buttons == 0 then flickerstreak@30: button:SetPoint("TOP", level, "TOP", 0, -10) flickerstreak@30: else flickerstreak@30: button:SetPoint("TOP", level.buttons[#level.buttons], "BOTTOM", 0, 0) flickerstreak@30: end flickerstreak@30: button.text:SetPoint("LEFT", button, "LEFT", 24, 0) flickerstreak@30: button:Show() flickerstreak@30: button.level = level flickerstreak@30: table.insert(level.buttons, button) flickerstreak@30: if not level.parented then flickerstreak@30: level.parented = true flickerstreak@30: level:ClearAllPoints() flickerstreak@30: if level.num == 1 then flickerstreak@30: if level.parent ~= UIParent and type(level.parent) == "table" then flickerstreak@30: level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") flickerstreak@30: else flickerstreak@30: level:SetPoint("CENTER", UIParent, "CENTER") flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: level:SetFrameStrata("FULLSCREEN_DIALOG") flickerstreak@30: end flickerstreak@30: button:SetAlpha(1) flickerstreak@30: return button flickerstreak@30: end flickerstreak@30: flickerstreak@30: local numLevels = 0 flickerstreak@30: local function AcquireLevel(self, level) flickerstreak@30: if not levels[level] then flickerstreak@30: for i = #levels + 1, level, -1 do flickerstreak@30: local i = i flickerstreak@30: numLevels = numLevels + 1 flickerstreak@30: local frame = CreateFrame("Button", "Dewdrop20Level" .. numLevels, nil) flickerstreak@30: if i == 1 then flickerstreak@30: local old_CloseSpecialWindows = CloseSpecialWindows flickerstreak@30: function CloseSpecialWindows() flickerstreak@30: local found = old_CloseSpecialWindows() flickerstreak@30: if levels[1]:IsShown() then flickerstreak@30: self:Close() flickerstreak@30: return 1 flickerstreak@30: end flickerstreak@30: return found flickerstreak@30: end flickerstreak@30: end flickerstreak@30: levels[i] = frame flickerstreak@30: frame.num = i flickerstreak@30: frame:SetParent(UIParent) flickerstreak@30: frame:SetFrameStrata("FULLSCREEN_DIALOG") flickerstreak@30: frame:Hide() flickerstreak@30: frame:SetWidth(180) flickerstreak@30: frame:SetHeight(10) flickerstreak@30: frame:SetFrameLevel(i * 3) flickerstreak@30: frame:SetScript("OnHide", function() flickerstreak@30: self:Close(level + 1) flickerstreak@30: end) flickerstreak@30: if frame.SetTopLevel then flickerstreak@30: frame:SetTopLevel(true) flickerstreak@30: end flickerstreak@30: frame:EnableMouse(true) flickerstreak@30: frame:EnableMouseWheel(true) flickerstreak@30: local backdrop = CreateFrame("Frame", nil, frame) flickerstreak@30: backdrop:SetAllPoints(frame) flickerstreak@30: backdrop:SetBackdrop(tmp( flickerstreak@30: 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", flickerstreak@30: 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", flickerstreak@30: 'tile', true, flickerstreak@30: 'insets', tmp2( flickerstreak@30: 'left', 5, flickerstreak@30: 'right', 5, flickerstreak@30: 'top', 5, flickerstreak@30: 'bottom', 5 flickerstreak@30: ), flickerstreak@30: 'tileSize', 16, flickerstreak@30: 'edgeSize', 16 flickerstreak@30: )) flickerstreak@30: backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) flickerstreak@30: backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) flickerstreak@30: frame:SetScript("OnClick", function() flickerstreak@30: self:Close(i) flickerstreak@30: end) flickerstreak@30: frame:SetScript("OnEnter", function() flickerstreak@30: StopCounting(self, i) flickerstreak@30: end) flickerstreak@30: frame:SetScript("OnLeave", function() flickerstreak@30: StartCounting(self, i) flickerstreak@30: end) flickerstreak@30: frame:SetScript("OnMouseWheel", function() flickerstreak@30: Scroll(self, frame, arg1 < 0) flickerstreak@30: end) flickerstreak@30: if i == 1 then flickerstreak@30: frame:SetScript("OnUpdate", function(this, arg1) flickerstreak@30: OnUpdate(self, arg1) flickerstreak@30: end) flickerstreak@30: levels[1].lastDirection = "RIGHT" flickerstreak@30: levels[1].lastVDirection = "DOWN" flickerstreak@30: else flickerstreak@30: levels[i].lastDirection = levels[i - 1].lastDirection flickerstreak@30: levels[i].lastVDirection = levels[i - 1].lastVDirection flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local fullscreenFrame = GetUIPanel("fullscreen") flickerstreak@30: local l = levels[level] flickerstreak@30: local strata, framelevel = l:GetFrameStrata(), l:GetFrameLevel() flickerstreak@30: if fullscreenFrame then flickerstreak@30: l:SetParent(fullscreenFrame) flickerstreak@30: else flickerstreak@30: l:SetParent(UIParent) flickerstreak@30: end flickerstreak@30: l:SetFrameStrata(strata) flickerstreak@30: l:SetFrameLevel(framelevel) flickerstreak@30: l:SetAlpha(1) flickerstreak@30: return l flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function validateOptions(options, position, baseOptions, fromPass) flickerstreak@30: if not baseOptions then flickerstreak@30: baseOptions = options flickerstreak@30: end flickerstreak@30: if type(options) ~= "table" then flickerstreak@30: return "Options must be a table.", position flickerstreak@30: end flickerstreak@30: local kind = options.type flickerstreak@30: if type(kind) ~= "string" then flickerstreak@30: return '"type" must be a string.', position flickerstreak@30: elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "dragLink" and kind ~= "header" then flickerstreak@30: return '"type" must either be "range", "text", "group", "toggle", "execute", "color", "dragLink", or "header".', position flickerstreak@30: end flickerstreak@30: if options.aliases then flickerstreak@30: if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then flickerstreak@30: return '"alias" must be a table or string', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if not fromPass then flickerstreak@30: if kind == "execute" then flickerstreak@30: if type(options.func) ~= "string" and type(options.func) ~= "function" then flickerstreak@30: return '"func" must be a string or function', position flickerstreak@30: end flickerstreak@30: elseif kind == "range" or kind == "text" or kind == "toggle" then flickerstreak@30: if type(options.set) ~= "string" and type(options.set) ~= "function" then flickerstreak@30: return '"set" must be a string or function', position flickerstreak@30: end flickerstreak@30: if kind == "text" and options.get == false then flickerstreak@30: elseif type(options.get) ~= "string" and type(options.get) ~= "function" then flickerstreak@30: return '"get" must be a string or function', position flickerstreak@30: end flickerstreak@30: elseif kind == "group" and options.pass then flickerstreak@30: if options.pass ~= true then flickerstreak@30: return '"pass" must be either nil, true, or false', position flickerstreak@30: end flickerstreak@30: if not options.func then flickerstreak@30: if type(options.set) ~= "string" and type(options.set) ~= "function" then flickerstreak@30: return '"set" must be a string or function', position flickerstreak@30: end flickerstreak@30: if type(options.get) ~= "string" and type(options.get) ~= "function" then flickerstreak@30: return '"get" must be a string or function', position flickerstreak@30: end flickerstreak@30: elseif type(options.func) ~= "string" and type(options.func) ~= "function" then flickerstreak@30: return '"func" must be a string or function', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options ~= baseOptions then flickerstreak@30: if kind == "header" then flickerstreak@30: elseif type(options.desc) ~= "string" then flickerstreak@30: return '"desc" must be a string', position flickerstreak@30: elseif options.desc:len() == 0 then flickerstreak@30: return '"desc" cannot be a 0-length string', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then flickerstreak@30: if options.type == "header" and not options.cmdName and not options.name then flickerstreak@30: elseif options.cmdName then flickerstreak@30: if type(options.cmdName) ~= "string" then flickerstreak@30: return '"cmdName" must be a string or nil', position flickerstreak@30: elseif options.cmdName:len() == 0 then flickerstreak@30: return '"cmdName" cannot be a 0-length string', position flickerstreak@30: end flickerstreak@30: if type(options.guiName) ~= "string" then flickerstreak@30: if not options.guiNameIsMap then flickerstreak@30: return '"guiName" must be a string or nil', position flickerstreak@30: end flickerstreak@30: elseif options.guiName:len() == 0 then flickerstreak@30: return '"guiName" cannot be a 0-length string', position flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if type(options.name) ~= "string" then flickerstreak@30: return '"name" must be a string', position flickerstreak@30: elseif options.name:len() == 0 then flickerstreak@30: return '"name" cannot be a 0-length string', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.guiNameIsMap then flickerstreak@30: if type(options.guiNameIsMap) ~= "boolean" then flickerstreak@30: return '"guiNameIsMap" must be a boolean or nil', position flickerstreak@30: elseif options.type ~= "toggle" then flickerstreak@30: return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position flickerstreak@30: elseif type(options.map) ~= "table" then flickerstreak@30: return '"map" must be a table', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.message and type(options.message) ~= "string" then flickerstreak@30: return '"message" must be a string or nil', position flickerstreak@30: end flickerstreak@30: if options.error and type(options.error) ~= "string" then flickerstreak@30: return '"error" must be a string or nil', position flickerstreak@30: end flickerstreak@30: if options.current and type(options.current) ~= "string" then flickerstreak@30: return '"current" must be a string or nil', position flickerstreak@30: end flickerstreak@30: if options.order then flickerstreak@30: if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then flickerstreak@30: return '"order" must be a non-zero number or nil', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.disabled then flickerstreak@30: if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then flickerstreak@30: return '"disabled" must be a function, string, or boolean', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.cmdHidden then flickerstreak@30: if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then flickerstreak@30: return '"cmdHidden" must be a function, string, or boolean', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.guiHidden then flickerstreak@30: if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then flickerstreak@30: return '"guiHidden" must be a function, string, or boolean', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.hidden then flickerstreak@30: if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then flickerstreak@30: return '"hidden" must be a function, string, or boolean', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if kind == "text" then flickerstreak@30: if type(options.validate) == "table" then flickerstreak@30: local t = options.validate flickerstreak@30: local iTable = nil flickerstreak@30: for k,v in pairs(t) do flickerstreak@30: if type(k) == "number" then flickerstreak@30: if iTable == nil then flickerstreak@30: iTable = true flickerstreak@30: elseif not iTable then flickerstreak@30: return '"validate" must either have all keys be indexed numbers or strings', position flickerstreak@30: elseif k < 1 or k > #t then flickerstreak@30: return '"validate" numeric keys must be indexed properly. >= 1 and <= #t', position flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if iTable == nil then flickerstreak@30: iTable = false flickerstreak@30: elseif iTable then flickerstreak@30: return '"validate" must either have all keys be indexed numbers or strings', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if type(v) ~= "string" then flickerstreak@30: return '"validate" values must all be strings', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.multiToggle and options.multiToggle ~= true then flickerstreak@30: return '"multiToggle" must be a boolean or nil if "validate" is a table', position flickerstreak@30: end flickerstreak@30: elseif options.validate == "keybinding" then flickerstreak@30: -- no other checks flickerstreak@30: else flickerstreak@30: if type(options.usage) ~= "string" then flickerstreak@30: return '"usage" must be a string', position flickerstreak@30: elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then flickerstreak@30: return '"validate" must be a string, function, or table', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.multiToggle and type(options.validate) ~= "table" then flickerstreak@30: return '"validate" must be a table if "multiToggle" is true', position flickerstreak@30: end flickerstreak@30: elseif kind == "range" then flickerstreak@30: if options.min or options.max then flickerstreak@30: if type(options.min) ~= "number" then flickerstreak@30: return '"min" must be a number', position flickerstreak@30: elseif type(options.max) ~= "number" then flickerstreak@30: return '"max" must be a number', position flickerstreak@30: elseif options.min >= options.max then flickerstreak@30: return '"min" must be less than "max"', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.step then flickerstreak@30: if type(options.step) ~= "number" then flickerstreak@30: return '"step" must be a number', position flickerstreak@30: elseif options.step < 0 then flickerstreak@30: return '"step" must be nonnegative', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.bigStep then flickerstreak@30: if type(options.bigStep) ~= "number" then flickerstreak@30: return '"bigStep" must be a number', position flickerstreak@30: elseif options.bigStep < 0 then flickerstreak@30: return '"bigStep" must be nonnegative', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.isPercent and options.isPercent ~= true then flickerstreak@30: return '"isPercent" must either be nil, true, or false', position flickerstreak@30: end flickerstreak@30: elseif kind == "toggle" then flickerstreak@30: if options.map then flickerstreak@30: if type(options.map) ~= "table" then flickerstreak@30: return '"map" must be a table', position flickerstreak@30: elseif type(options.map[true]) ~= "string" then flickerstreak@30: return '"map[true]" must be a string', position flickerstreak@30: elseif type(options.map[false]) ~= "string" then flickerstreak@30: return '"map[false]" must be a string', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: elseif kind == "color" then flickerstreak@30: if options.hasAlpha and options.hasAlpha ~= true then flickerstreak@30: return '"hasAlpha" must be nil, true, or false', position flickerstreak@30: end flickerstreak@30: elseif kind == "group" then flickerstreak@30: if options.pass and options.pass ~= true then flickerstreak@30: return '"pass" must be nil, true, or false', position flickerstreak@30: end flickerstreak@30: if type(options.args) ~= "table" then flickerstreak@30: return '"args" must be a table', position flickerstreak@30: end flickerstreak@30: for k,v in pairs(options.args) do flickerstreak@30: if type(k) ~= "number" then flickerstreak@30: if type(k) ~= "string" then flickerstreak@30: return '"args" keys must be strings or numbers', position flickerstreak@30: elseif k:len() == 0 then flickerstreak@30: return '"args" keys must not be 0-length strings.', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if type(v) ~= "table" then flickerstreak@30: return '"args" values must be tables', position and position .. "." .. k or k flickerstreak@30: end flickerstreak@30: local newposition flickerstreak@30: if position then flickerstreak@30: newposition = position .. ".args." .. k flickerstreak@30: else flickerstreak@30: newposition = "args." .. k flickerstreak@30: end flickerstreak@30: local err, pos = validateOptions(v, newposition, baseOptions, options.pass) flickerstreak@30: if err then flickerstreak@30: return err, pos flickerstreak@30: end flickerstreak@30: end flickerstreak@30: elseif kind == "execute" then flickerstreak@30: if type(options.confirm) ~= "string" and type(options.confirm) ~= "boolean" and type(options.confirm) ~= "nil" then flickerstreak@30: return '"confirm" must be a string, boolean, or nil', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.icon and type(options.icon) ~= "string" then flickerstreak@30: return'"icon" must be a string', position flickerstreak@30: end flickerstreak@30: if options.iconWidth or options.iconHeight then flickerstreak@30: if type(options.iconWidth) ~= "number" or type(options.iconHeight) ~= "number" then flickerstreak@30: return '"iconHeight" and "iconWidth" must be numbers', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if options.iconCoordLeft or options.iconCoordRight or options.iconCoordTop or options.iconCoordBottom then flickerstreak@30: if type(options.iconCoordLeft) ~= "number" or type(options.iconCoordRight) ~= "number" or type(options.iconCoordTop) ~= "number" or type(options.iconCoordBottom) ~= "number" then flickerstreak@30: return '"iconCoordLeft", "iconCoordRight", "iconCoordTop", and "iconCoordBottom" must be numbers', position flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local validatedOptions flickerstreak@30: flickerstreak@30: local values flickerstreak@30: local mysort_args flickerstreak@30: local mysort flickerstreak@30: local othersort flickerstreak@30: local othersort_validate flickerstreak@30: flickerstreak@30: local baseFunc, currentLevel flickerstreak@30: flickerstreak@30: local function confirmPopup(message, func, ...) flickerstreak@30: if not StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] then flickerstreak@30: StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] = {} flickerstreak@30: end flickerstreak@30: local t = StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] flickerstreak@30: for k in pairs(t) do flickerstreak@30: t[k] = nil flickerstreak@30: end flickerstreak@30: t.text = message flickerstreak@30: t.button1 = ACCEPT or "Accept" flickerstreak@30: t.button2 = CANCEL or "Cancel" flickerstreak@30: t.OnAccept = function() flickerstreak@30: func(unpack(t)) flickerstreak@30: end flickerstreak@30: for i = 1, select('#', ...) do flickerstreak@30: t[i] = select(i, ...) flickerstreak@30: end flickerstreak@30: t.timeout = 0 flickerstreak@30: t.whileDead = 1 flickerstreak@30: t.hideOnEscape = 1 flickerstreak@30: flickerstreak@30: Dewdrop:Close() flickerstreak@30: StaticPopup_Show("DEWDROP20_CONFIRM_DIALOG") flickerstreak@30: end flickerstreak@30: flickerstreak@30: flickerstreak@30: local function getMethod(settingname, handler, v, methodName, ...) -- "..." is simply returned straight out cause you can't do "a,b,c = 111,f(),222" flickerstreak@30: assert(v and type(v)=="table") flickerstreak@30: assert(methodName and type(methodName)=="string") flickerstreak@30: flickerstreak@30: local method = v[methodName] flickerstreak@30: if type(method)=="function" then flickerstreak@30: return method, ... flickerstreak@30: elseif type(method)=="string" then flickerstreak@30: if not handler then flickerstreak@30: Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) flickerstreak@30: elseif not handler[method] then flickerstreak@30: Dewdrop:error("[%s] 'handler' method %q not defined", tostring(settingname), method) flickerstreak@30: end flickerstreak@30: return handler[method], handler, ... flickerstreak@30: end flickerstreak@30: flickerstreak@30: Dewdrop:error("[%s] Missing %q directive", tostring(settingname), methodName) flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function callMethod(settingname, handler, v, methodName, ...) flickerstreak@30: assert(v and type(v)=="table") flickerstreak@30: assert(methodName and type(methodName)=="string") flickerstreak@30: flickerstreak@30: local method = v[methodName] flickerstreak@30: if type(method)=="function" then flickerstreak@30: local success, ret,ret2,ret3,ret4 = pcall(v[methodName], ...) flickerstreak@30: if not success then flickerstreak@30: geterrorhandler()(ret) flickerstreak@30: return nil flickerstreak@30: end flickerstreak@30: return ret,ret2,ret3,ret4 flickerstreak@30: flickerstreak@30: elseif type(method)=="string" then flickerstreak@30: flickerstreak@30: local neg = method:match("^~(.-)$") flickerstreak@30: if neg then flickerstreak@30: method = neg flickerstreak@30: end flickerstreak@30: if not handler then flickerstreak@30: Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) flickerstreak@30: elseif not handler[method] then flickerstreak@30: Dewdrop:error("[%s] 'handler' (%q) method %q not defined", tostring(settingname), handler.name or "(unnamed)", method) flickerstreak@30: end flickerstreak@30: local success, ret,ret2,ret3,ret4 = pcall(handler[method], handler, ...) flickerstreak@30: if not success then flickerstreak@30: geterrorhandler()(ret) flickerstreak@30: return nil flickerstreak@30: end flickerstreak@30: if neg then flickerstreak@30: return not ret flickerstreak@30: end flickerstreak@30: return ret,ret2,ret3,ret4 flickerstreak@30: elseif method == false then flickerstreak@30: return nil flickerstreak@30: end flickerstreak@30: flickerstreak@30: Dewdrop:error("[%s] Missing %q directive in %q", tostring(settingname), methodName, v.name or "(unnamed)") flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function skip1Nil(...) flickerstreak@30: if select(1,...)==nil then flickerstreak@30: return select(2,...) flickerstreak@30: end flickerstreak@30: return ... flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:FeedAceOptionsTable(options, difference) flickerstreak@30: self:argCheck(options, 2, "table") flickerstreak@30: self:argCheck(difference, 3, "nil", "number") flickerstreak@30: if not currentLevel then flickerstreak@30: self:error("Cannot call `FeedAceOptionsTable' outside of a Dewdrop declaration") flickerstreak@30: end flickerstreak@30: if not difference then flickerstreak@30: difference = 0 flickerstreak@30: end flickerstreak@30: if not validatedOptions then flickerstreak@30: validatedOptions = {} flickerstreak@30: end flickerstreak@30: if not validatedOptions[options] then flickerstreak@30: local err, position = validateOptions(options) flickerstreak@30: flickerstreak@30: if err then flickerstreak@30: if position then flickerstreak@30: Dewdrop:error(position .. ": " .. err) flickerstreak@30: else flickerstreak@30: Dewdrop:error(err) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: validatedOptions[options] = true flickerstreak@30: end flickerstreak@30: local level = levels[currentLevel] flickerstreak@30: if not level then flickerstreak@30: self:error("Improper level given") flickerstreak@30: end flickerstreak@30: if not values then flickerstreak@30: values = {} flickerstreak@30: else flickerstreak@30: for k,v in pairs(values) do flickerstreak@30: values[k] = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local current = level flickerstreak@30: while current do -- this traverses from higher level numbers to lower, building "values" with leaf nodes first and trunk nodes later flickerstreak@30: if current.num == difference + 1 then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: table.insert(values, current.value) flickerstreak@30: current = levels[current.num - 1] flickerstreak@30: end flickerstreak@30: flickerstreak@30: local realOptions = options flickerstreak@30: local handler = options.handler flickerstreak@30: local passTable flickerstreak@30: local passValue flickerstreak@30: while #values > 0 do -- This loop traverses values from the END (trunk nodes first, then onto leaf nodes) flickerstreak@30: if options.pass then flickerstreak@30: if options.get and options.set then flickerstreak@30: passTable = options flickerstreak@30: elseif not passTable then flickerstreak@30: passTable = options flickerstreak@30: end flickerstreak@30: else flickerstreak@30: passTable = nil flickerstreak@30: end flickerstreak@30: local value = table.remove(values) flickerstreak@30: options = options.args and options.args[value] flickerstreak@30: if not options then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: handler = options.handler or handler flickerstreak@30: passValue = passTable and value or nil flickerstreak@30: end flickerstreak@30: flickerstreak@30: if options.type == "group" then flickerstreak@30: local hidden = options.hidden flickerstreak@30: if type(hidden) == "function" or type(hidden) == "string" then flickerstreak@30: hidden = callMethod(options.name or "(options root)", handler, options, "hidden", options.passValue) or false flickerstreak@30: end flickerstreak@30: if hidden then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: local disabled = options.disabled flickerstreak@30: if type(disabled) == "function" or type(disabled) == "string" then flickerstreak@30: disabled = callMethod(options.name or "(options root)", handler, options, "disabled", options.passValue) or false flickerstreak@30: end flickerstreak@30: if disabled then flickerstreak@30: self:AddLine( flickerstreak@30: 'text', DISABLED, flickerstreak@30: 'disabled', true flickerstreak@30: ) flickerstreak@30: return flickerstreak@30: end flickerstreak@30: for k in pairs(options.args) do flickerstreak@30: table.insert(values, k) flickerstreak@30: end flickerstreak@30: if options.pass then flickerstreak@30: if options.get and options.set then flickerstreak@30: passTable = options flickerstreak@30: elseif not passTable then flickerstreak@30: passTable = options flickerstreak@30: end flickerstreak@30: else flickerstreak@30: passTable = nil flickerstreak@30: end flickerstreak@30: if not mysort then flickerstreak@30: mysort = function(a, b) flickerstreak@30: local alpha, bravo = mysort_args[a], mysort_args[b] flickerstreak@30: local alpha_order = alpha.order or 100 flickerstreak@30: local bravo_order = bravo.order or 100 flickerstreak@30: local alpha_name = alpha.guiName or alpha.name flickerstreak@30: local bravo_name = bravo.guiName or bravo.name flickerstreak@30: if alpha_order == bravo_order then flickerstreak@30: if not alpha_name then flickerstreak@30: return bravo_name flickerstreak@30: elseif not bravo_name then flickerstreak@30: return false flickerstreak@30: else flickerstreak@30: return alpha_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < bravo_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if alpha_order < 0 then flickerstreak@30: if bravo_order > 0 then flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if bravo_order < 0 then flickerstreak@30: return true flickerstreak@30: end flickerstreak@30: end flickerstreak@30: return alpha_order < bravo_order flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: mysort_args = options.args flickerstreak@30: table.sort(values, mysort) flickerstreak@30: mysort_args = nil flickerstreak@30: local hasBoth = #values >= 1 and (options.args[values[1]].order or 100) > 0 and (options.args[values[#values]].order or 100) < 0 flickerstreak@30: local last_order = 1 flickerstreak@30: for _,k in ipairs(values) do flickerstreak@30: local v = options.args[k] flickerstreak@30: local handler = v.handler or handler flickerstreak@30: if hasBoth and last_order > 0 and (v.order or 100) < 0 then flickerstreak@30: hasBoth = false flickerstreak@30: self:AddLine() flickerstreak@30: end flickerstreak@30: local hidden, disabled = v.guiHidden or v.hidden, v.disabled flickerstreak@30: flickerstreak@30: if type(hidden) == "function" or type(hidden) == "string" then flickerstreak@30: hidden = callMethod(k, handler, v, "hidden", v.passValue) or false flickerstreak@30: end flickerstreak@30: if not hidden then flickerstreak@30: if type(disabled) == "function" or type(disabled) == "string" then flickerstreak@30: disabled = callMethod(k, handler, v, "disabled", v.passValue) or false flickerstreak@30: end flickerstreak@30: local name = (v.guiIconOnly and v.icon) and "" or (v.guiName or v.name) flickerstreak@30: local desc = v.guiDesc or v.desc flickerstreak@30: local iconHeight = v.iconHeight or 16 flickerstreak@30: local iconWidth = v.iconWidth or 16 flickerstreak@30: local iconCoordLeft = v.iconCoordLeft flickerstreak@30: local iconCoordRight = v.iconCoordRight flickerstreak@30: local iconCoordBottom = v.iconCoordBottom flickerstreak@30: local iconCoordTop = v.iconCoordTop flickerstreak@30: local tooltipTitle, tooltipText flickerstreak@30: tooltipTitle = name flickerstreak@30: if name ~= desc then flickerstreak@30: tooltipText = desc flickerstreak@30: end flickerstreak@30: if type(v.usage) == "string" and v.usage:trim():len() > 0 then flickerstreak@30: if tooltipText then flickerstreak@30: tooltipText = tooltipText .. "\n\n" .. USAGE_TOOLTIP:format(v.usage) flickerstreak@30: else flickerstreak@30: tooltipText = USAGE_TOOLTIP:format(v.usage) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local v_p = passTable flickerstreak@30: if not v_p or (v.type ~= "execute" and v.get and v.set) or (v.type == "execute" and v.func) then flickerstreak@30: v_p = v flickerstreak@30: end flickerstreak@30: local passValue = v.passValue or (v_p~=v and k) or nil flickerstreak@30: if v.type == "toggle" then flickerstreak@30: local checked = callMethod(name, handler, v_p, "get", passValue) or false flickerstreak@30: local checked_arg = checked flickerstreak@30: if type(v_p.get)=="string" and v_p.get:match("^~") then flickerstreak@30: checked_arg = not checked flickerstreak@30: end flickerstreak@30: local func, arg1, arg2, arg3 = getMethod(name, handler, v_p, "set", skip1Nil(passValue, not checked_arg)) flickerstreak@30: if v.guiNameIsMap then flickerstreak@30: checked = checked and true or false flickerstreak@30: name = tostring(v.map and v.map[checked]):gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") flickerstreak@30: tooltipTitle = name flickerstreak@30: checked = true--nil flickerstreak@30: end flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'checked', checked, flickerstreak@30: 'isRadio', v.isRadio, flickerstreak@30: 'func', func, flickerstreak@30: 'arg1', arg1, flickerstreak@30: 'arg2', arg2, flickerstreak@30: 'arg3', arg3, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText flickerstreak@30: ) flickerstreak@30: elseif v.type == "execute" then flickerstreak@30: local func, arg1, arg2, arg3, arg4 flickerstreak@30: local confirm = v.confirm flickerstreak@30: if confirm == true then flickerstreak@30: confirm = DEFAULT_CONFIRM_MESSAGE:format(tooltipText or tooltipTitle) flickerstreak@30: func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) flickerstreak@30: elseif type(confirm) == "string" then flickerstreak@30: func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) flickerstreak@30: else flickerstreak@30: func,arg1,arg2 = getMethod(name, handler, v_p, "func", passValue) flickerstreak@30: end flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'checked', checked, flickerstreak@30: 'func', func, flickerstreak@30: 'arg1', arg1, flickerstreak@30: 'arg2', arg2, flickerstreak@30: 'arg3', arg3, flickerstreak@30: 'arg4', arg4, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom flickerstreak@30: ) flickerstreak@30: elseif v.type == "range" then flickerstreak@30: local sliderValue flickerstreak@30: sliderValue = callMethod(name, handler, v_p, "get", passValue) or 0 flickerstreak@30: local sliderFunc, sliderArg1, sliderArg2 = getMethod(name, handler, v_p, "set", passValue) flickerstreak@30: if tooltipText then flickerstreak@30: tooltipText = format("%s\n\n%s", tooltipText, RANGE_TOOLTIP) flickerstreak@30: else flickerstreak@30: tooltipText = RANGE_TOOLTIP flickerstreak@30: end flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'hasArrow', true, flickerstreak@30: 'hasSlider', true, flickerstreak@30: 'sliderMin', v.min or 0, flickerstreak@30: 'sliderMax', v.max or 1, flickerstreak@30: 'sliderStep', v.step or 0, flickerstreak@30: 'sliderBigStep', v.bigStep or nil, flickerstreak@30: 'sliderIsPercent', v.isPercent or false, flickerstreak@30: 'sliderValue', sliderValue, flickerstreak@30: 'sliderFunc', sliderFunc, flickerstreak@30: 'sliderArg1', sliderArg1, flickerstreak@30: 'sliderArg2', sliderArg2, flickerstreak@30: 'fromAceOptions', true, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom flickerstreak@30: ) flickerstreak@30: elseif v.type == "color" then flickerstreak@30: local r,g,b,a = callMethod(name, handler, v_p, "get", passValue) flickerstreak@30: if not r then flickerstreak@30: r,g,b,a = 0,0,0,0 flickerstreak@30: end flickerstreak@30: local colorFunc, colorArg1, colorArg2 = getMethod(name, handler, v_p, "set", passValue) flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'hasArrow', true, flickerstreak@30: 'hasColorSwatch', true, flickerstreak@30: 'r', r, flickerstreak@30: 'g', g, flickerstreak@30: 'b', b, flickerstreak@30: 'opacity', v.hasAlpha and a or nil, flickerstreak@30: 'hasOpacity', v.hasAlpha, flickerstreak@30: 'colorFunc', colorFunc, flickerstreak@30: 'colorArg1', colorArg1, flickerstreak@30: 'colorArg2', colorArg2, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText flickerstreak@30: ) flickerstreak@30: elseif v.type == "text" then flickerstreak@30: if type(v.validate) == "table" then flickerstreak@30: local func,arg1,arg2 flickerstreak@30: if v.onClick then flickerstreak@30: func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) flickerstreak@30: end flickerstreak@30: local checked flickerstreak@30: if v.isChecked then flickerstreak@30: checked = callMethod(name, handler, v, "isChecked", passValue) or false flickerstreak@30: end flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'hasArrow', true, flickerstreak@30: 'value', k, flickerstreak@30: 'func', func, flickerstreak@30: 'arg1', arg1, flickerstreak@30: 'arg2', arg2, flickerstreak@30: 'mouseoverUnderline', func and true or nil, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'checked', checked, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom flickerstreak@30: ) flickerstreak@30: else flickerstreak@30: local editBoxText flickerstreak@30: editBoxText = callMethod(name, handler, v_p, "get", passValue) or "" flickerstreak@30: local editBoxFunc, editBoxArg1, editBoxArg2 = getMethod(name, handler, v_p, "set", passValue) flickerstreak@30: flickerstreak@30: local editBoxValidateFunc, editBoxValidateArg1 flickerstreak@30: flickerstreak@30: if v.validate and v.validate ~= "keybinding" then flickerstreak@30: if v.validate == "keybinding" then flickerstreak@30: if tooltipText then flickerstreak@30: tooltipText = format("%s\n\n%s", tooltipText, RESET_KEYBINDING_DESC) flickerstreak@30: else flickerstreak@30: tooltipText = RESET_KEYBINDING_DESC flickerstreak@30: end flickerstreak@30: else flickerstreak@30: editBoxValidateFunc, editBoxValidateArg1 = getMethod(name, handler, v, "validate") -- no passvalue! flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'hasArrow', true, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom, flickerstreak@30: 'hasEditBox', true, flickerstreak@30: 'editBoxText', editBoxText, flickerstreak@30: 'editBoxFunc', editBoxFunc, flickerstreak@30: 'editBoxArg1', editBoxArg1, flickerstreak@30: 'editBoxArg2', editBoxArg2, flickerstreak@30: 'editBoxValidateFunc', editBoxValidateFunc, flickerstreak@30: 'editBoxValidateArg1', editBoxValidateArg1, flickerstreak@30: 'editBoxIsKeybinding', v.validate == "keybinding", flickerstreak@30: 'editBoxKeybindingOnly', v.keybindingOnly, flickerstreak@30: 'editBoxKeybindingExcept', v.keybindingExcept, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText flickerstreak@30: ) flickerstreak@30: end flickerstreak@30: elseif v.type == "group" then flickerstreak@30: local func,arg1,arg2 flickerstreak@30: if v.onClick then flickerstreak@30: func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) flickerstreak@30: end flickerstreak@30: local checked flickerstreak@30: if v.isChecked then flickerstreak@30: checked = callMethod(name, handler, v, "isChecked", passValue) or false flickerstreak@30: end flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'hasArrow', true, flickerstreak@30: 'value', k, flickerstreak@30: 'func', func, flickerstreak@30: 'arg1', arg1, flickerstreak@30: 'arg2', arg2, flickerstreak@30: 'mouseoverUnderline', func and true or nil, flickerstreak@30: 'disabled', disabled, flickerstreak@30: 'checked', checked, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom flickerstreak@30: ) flickerstreak@30: elseif v.type == "header" then flickerstreak@30: if name == "" or not name then flickerstreak@30: self:AddLine( flickerstreak@30: 'isTitle', true, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom flickerstreak@30: ) flickerstreak@30: else flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'isTitle', true, flickerstreak@30: 'icon', v.icon, flickerstreak@30: 'iconHeight', iconHeight, flickerstreak@30: 'iconWidth', iconWidth, flickerstreak@30: 'iconCoordLeft', iconCoordLeft, flickerstreak@30: 'iconCoordRight', iconCoordRight, flickerstreak@30: 'iconCoordTop', iconCoordTop, flickerstreak@30: 'iconCoordBottom', iconCoordBottom flickerstreak@30: ) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: last_order = v.order or 100 flickerstreak@30: end flickerstreak@30: elseif options.type == "text" and type(options.validate) == "table" then flickerstreak@30: local current flickerstreak@30: local options_p = passTable flickerstreak@30: if not options_p or (options.get and options.set) then flickerstreak@30: options_p = options flickerstreak@30: passTable = nil flickerstreak@30: passValue = nil flickerstreak@30: end flickerstreak@30: local multiToggle = options.multiToggle flickerstreak@30: local passValue = options.passValue or passValue flickerstreak@30: if not multiToggle then flickerstreak@30: current = callMethod(k, handler, options_p, "get", passValue) flickerstreak@30: end flickerstreak@30: local indexed = true flickerstreak@30: for k,v in pairs(options.validate) do flickerstreak@30: if type(k) ~= "number" then flickerstreak@30: indexed = false flickerstreak@30: end flickerstreak@30: table.insert(values, k) flickerstreak@30: end flickerstreak@30: if not indexed then flickerstreak@30: if not othersort then flickerstreak@30: othersort = function(alpha, bravo) flickerstreak@30: return othersort_validate[alpha]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < othersort_validate[bravo]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: othersort_validate = options.validate flickerstreak@30: table.sort(values, othersort) flickerstreak@30: othersort_validate = nil flickerstreak@30: end flickerstreak@30: for _,k in ipairs(values) do flickerstreak@30: local v = options.validate[k] flickerstreak@30: if type(k) == "number" then flickerstreak@30: k = v flickerstreak@30: end flickerstreak@30: local func, arg1, arg2, arg3, arg4 = getMethod(k, handler, options_p, "set", skip1Nil(passValue, k)) flickerstreak@30: local checked flickerstreak@30: if multiToggle then flickerstreak@30: checked = callMethod(k, handler, options_p, "get", skip1Nil(passValue, k)) or false flickerstreak@30: if arg2 == nil then flickerstreak@30: arg2 = not checked flickerstreak@30: elseif arg3 == nil then flickerstreak@30: arg3 = not checked flickerstreak@30: else flickerstreak@30: arg4 = not checked flickerstreak@30: end flickerstreak@30: else flickerstreak@30: checked = (k == current or (type(k) == "string" and type(current) == "string" and k:lower() == current:lower())) flickerstreak@30: if checked then flickerstreak@30: func, arg1, arg2, arg3, arg4 = nil, nil, nil, nil, nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local tooltipTitle flickerstreak@30: local tooltipText flickerstreak@30: if options.validateDesc then flickerstreak@30: tooltipTitle = v flickerstreak@30: tooltipText = options.validateDesc[k] flickerstreak@30: else flickerstreak@30: tooltipTitle = options.guiName or options.name flickerstreak@30: tooltipText = v flickerstreak@30: end flickerstreak@30: self:AddLine( flickerstreak@30: 'text', v, flickerstreak@30: 'func', func, flickerstreak@30: 'arg1', arg1, flickerstreak@30: 'arg2', arg2, flickerstreak@30: 'arg3', arg3, flickerstreak@30: 'arg4', arg4, flickerstreak@30: 'isRadio', not multiToggle, flickerstreak@30: 'checked', checked, flickerstreak@30: 'tooltipTitle', tooltipTitle, flickerstreak@30: 'tooltipText', tooltipText flickerstreak@30: ) flickerstreak@30: end flickerstreak@30: for k in pairs(values) do flickerstreak@30: values[k] = nil flickerstreak@30: end flickerstreak@30: else flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: return true flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:FeedTable(s, difference) flickerstreak@30: self:argCheck(s, 2, "table") flickerstreak@30: self:argCheck(difference, 3, "nil", "number") flickerstreak@30: if not currentLevel then flickerstreak@30: self:error("Cannot call `FeedTable' outside of a Dewdrop declaration") flickerstreak@30: end flickerstreak@30: if not difference then flickerstreak@30: difference = 0 flickerstreak@30: end flickerstreak@30: local level = levels[currentLevel] flickerstreak@30: if not level then flickerstreak@30: self:error("Improper level given") flickerstreak@30: end flickerstreak@30: if not values then flickerstreak@30: values = {} flickerstreak@30: else flickerstreak@30: for k,v in pairs(values) do flickerstreak@30: values[k] = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local t = s.subMenu and s or {subMenu = s} flickerstreak@30: local current = level flickerstreak@30: while current do flickerstreak@30: if current.num == difference + 1 then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: table.insert(values, current.value) flickerstreak@30: current = levels[current.num - 1] flickerstreak@30: end flickerstreak@30: flickerstreak@30: while #values > 0 do flickerstreak@30: local value = table.remove(values) flickerstreak@30: t = t.subMenu and t.subMenu[value] flickerstreak@30: if not t then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: if t.subMenu or current.num == 1 then flickerstreak@30: for k in pairs(t.subMenu) do flickerstreak@30: table.insert(values, k) flickerstreak@30: end flickerstreak@30: table.sort(values) flickerstreak@30: for _,k in ipairs(values) do flickerstreak@30: local argTable = {"value", k} flickerstreak@30: for key, val in pairs(t.subMenu[k]) do flickerstreak@30: table.insert(argTable, key) flickerstreak@30: table.insert(argTable, val) flickerstreak@30: end flickerstreak@30: self:AddLine(unpack(argTable)) flickerstreak@30: end flickerstreak@30: for k in pairs(values) do flickerstreak@30: values[k] = nil flickerstreak@30: end flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: return true flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Refresh(self, level) flickerstreak@30: if type(level) == "number" then flickerstreak@30: level = levels[level] flickerstreak@30: end flickerstreak@30: if not level then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: if baseFunc then flickerstreak@30: Clear(self, level) flickerstreak@30: currentLevel = level.num flickerstreak@30: if type(baseFunc) == "table" then flickerstreak@30: if currentLevel == 1 then flickerstreak@30: local handler = baseFunc.handler flickerstreak@30: if handler then flickerstreak@30: local name = tostring(handler) flickerstreak@30: if not name:find('^table:') and not handler.hideMenuTitle then flickerstreak@30: name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") flickerstreak@30: self:AddLine( flickerstreak@30: 'text', name, flickerstreak@30: 'isTitle', true flickerstreak@30: ) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: -- elseif level.parentText then flickerstreak@30: -- self:AddLine( flickerstreak@30: -- 'text', level.parentText, flickerstreak@30: -- 'tooltipTitle', level.parentTooltipTitle, flickerstreak@30: -- 'tooltipText', level.parentTooltipText, flickerstreak@30: -- 'tooltipFunc', level.parentTooltipFunc, flickerstreak@30: -- 'isTitle', true flickerstreak@30: -- ) flickerstreak@30: end flickerstreak@30: self:FeedAceOptionsTable(baseFunc) flickerstreak@30: if currentLevel == 1 then flickerstreak@30: self:AddLine( flickerstreak@30: 'text', CLOSE, flickerstreak@30: 'tooltipTitle', CLOSE, flickerstreak@30: 'tooltipText', CLOSE_DESC, flickerstreak@30: 'closeWhenClicked', true flickerstreak@30: ) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: -- if level.parentText then flickerstreak@30: -- self:AddLine( flickerstreak@30: -- 'text', level.parentText, flickerstreak@30: -- 'tooltipTitle', level.parentTooltipTitle, flickerstreak@30: -- 'tooltipText', level.parentTooltipText, flickerstreak@30: -- 'tooltipFunc', level.parentTooltipFunc, flickerstreak@30: -- 'isTitle', true flickerstreak@30: -- ) flickerstreak@30: -- end flickerstreak@30: 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) flickerstreak@30: end flickerstreak@30: currentLevel = nil flickerstreak@30: CheckSize(self, level) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:Refresh(level) flickerstreak@30: self:argCheck(level, 2, "number", "nil") flickerstreak@30: if not level then flickerstreak@30: for k,v in pairs(levels) do flickerstreak@30: Refresh(self, v) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: Refresh(self, levels[level]) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: function OpenSlider(self, parent) flickerstreak@30: if not sliderFrame then flickerstreak@30: sliderFrame = CreateFrame("Frame", nil, nil) flickerstreak@30: sliderFrame:SetWidth(100) flickerstreak@30: sliderFrame:SetHeight(170) flickerstreak@30: sliderFrame:SetScale(UIParent:GetScale()) flickerstreak@30: sliderFrame:SetBackdrop(tmp( flickerstreak@30: 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", flickerstreak@30: 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", flickerstreak@30: 'tile', true, flickerstreak@30: 'insets', tmp2( flickerstreak@30: 'left', 5, flickerstreak@30: 'right', 5, flickerstreak@30: 'top', 5, flickerstreak@30: 'bottom', 5 flickerstreak@30: ), flickerstreak@30: 'tileSize', 16, flickerstreak@30: 'edgeSize', 16 flickerstreak@30: )) flickerstreak@30: sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG") flickerstreak@30: if sliderFrame.SetTopLevel then flickerstreak@30: sliderFrame:SetTopLevel(true) flickerstreak@30: end flickerstreak@30: sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) flickerstreak@30: sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) flickerstreak@30: sliderFrame:EnableMouse(true) flickerstreak@30: sliderFrame:EnableMouseWheel(true) flickerstreak@30: sliderFrame:Hide() flickerstreak@30: sliderFrame:SetPoint("CENTER", UIParent, "CENTER") flickerstreak@30: local slider = CreateFrame("Slider", nil, sliderFrame) flickerstreak@30: sliderFrame.slider = slider flickerstreak@30: slider:SetOrientation("VERTICAL") flickerstreak@30: slider:SetMinMaxValues(0, 1) flickerstreak@30: slider:SetValueStep(0.000000001) flickerstreak@30: slider:SetValue(0.5) flickerstreak@30: slider:SetWidth(16) flickerstreak@30: slider:SetHeight(128) flickerstreak@30: slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) flickerstreak@30: slider:SetBackdrop(tmp( flickerstreak@30: 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", flickerstreak@30: 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", flickerstreak@30: 'tile', true, flickerstreak@30: 'edgeSize', 8, flickerstreak@30: 'tileSize', 8, flickerstreak@30: 'insets', tmp2( flickerstreak@30: 'left', 3, flickerstreak@30: 'right', 3, flickerstreak@30: 'top', 3, flickerstreak@30: 'bottom', 3 flickerstreak@30: ) flickerstreak@30: )) flickerstreak@30: local texture = slider:CreateTexture() flickerstreak@30: slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") flickerstreak@30: local text = slider:CreateFontString(nil, "ARTWORK") flickerstreak@30: sliderFrame.topText = text flickerstreak@30: text:SetFontObject(GameFontGreenSmall) flickerstreak@30: text:SetText("100%") flickerstreak@30: text:SetPoint("BOTTOM", slider, "TOP") flickerstreak@30: local text = slider:CreateFontString(nil, "ARTWORK") flickerstreak@30: sliderFrame.bottomText = text flickerstreak@30: text:SetFontObject(GameFontGreenSmall) flickerstreak@30: text:SetText("0%") flickerstreak@30: text:SetPoint("TOP", slider, "BOTTOM") flickerstreak@30: local editBox = CreateFrame("EditBox", nil, sliderFrame) flickerstreak@30: sliderFrame.currentText = editBox flickerstreak@30: editBox:SetFontObject(ChatFontNormal) flickerstreak@30: editBox:SetHeight(13) flickerstreak@30: editBox:SetPoint("RIGHT", sliderFrame, "RIGHT", -16, 0) flickerstreak@30: editBox:SetPoint("LEFT", slider, "RIGHT", 12, 0) flickerstreak@30: editBox:SetText("50%") flickerstreak@30: editBox:SetJustifyH("CENTER") flickerstreak@30: flickerstreak@30: local width = editBox:GetWidth()/2 + 10 flickerstreak@30: local left = editBox:CreateTexture(nil, "BACKGROUND") flickerstreak@30: left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") flickerstreak@30: left:SetTexCoord(0, width / 256, 0, 1) flickerstreak@30: left:SetWidth(width) flickerstreak@30: left:SetHeight(32) flickerstreak@30: left:SetPoint("LEFT", editBox, "LEFT", -10, 0) flickerstreak@30: local right = editBox:CreateTexture(nil, "BACKGROUND") flickerstreak@30: right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") flickerstreak@30: right:SetTexCoord(1 - width / 256, 1, 0, 1) flickerstreak@30: right:SetWidth(width) flickerstreak@30: right:SetHeight(32) flickerstreak@30: right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) flickerstreak@30: flickerstreak@30: local changed = false flickerstreak@30: local inside = false flickerstreak@30: slider:SetScript("OnValueChanged", function() flickerstreak@30: if sliderFrame.changing then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: changed = true flickerstreak@30: local done = false flickerstreak@30: if sliderFrame.parent and sliderFrame.parent.sliderFunc then flickerstreak@30: local min = sliderFrame.parent.sliderMin or 0 flickerstreak@30: local max = sliderFrame.parent.sliderMax or 1 flickerstreak@30: local step flickerstreak@30: if sliderFrame.fineStep then flickerstreak@30: step = sliderFrame.parent.sliderStep or (max - min) / 100 flickerstreak@30: else flickerstreak@30: step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 flickerstreak@30: end flickerstreak@30: local value = (1 - slider:GetValue()) * (max - min) + min flickerstreak@30: if step > 0 then flickerstreak@30: value = math.floor((value - min) / step + 0.5) * step + min flickerstreak@30: if value > max then flickerstreak@30: value = max flickerstreak@30: elseif value < min then flickerstreak@30: value = min flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if value == sliderFrame.lastValue then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: sliderFrame.lastValue = value flickerstreak@30: local text = sliderFrame.parent.sliderFunc(getArgs(sliderFrame.parent, 'sliderArg', 1, value)) flickerstreak@30: if sliderFrame.parent.fromAceOptions then flickerstreak@30: text = nil flickerstreak@30: elseif type(text) == "string" or type(text) == "number" then flickerstreak@30: sliderFrame.currentText:SetText(text) flickerstreak@30: done = true flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if not done then flickerstreak@30: local min = sliderFrame.parent.sliderMin or 0 flickerstreak@30: local max = sliderFrame.parent.sliderMax or 1 flickerstreak@30: local step flickerstreak@30: if sliderFrame.fineStep then flickerstreak@30: step = sliderFrame.parent.sliderStep or (max - min) / 100 flickerstreak@30: else flickerstreak@30: step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 flickerstreak@30: end flickerstreak@30: local value = (1 - slider:GetValue()) * (max - min) + min flickerstreak@30: if step > 0 then flickerstreak@30: value = math.floor((value - min) / step + 0.5) * step + min flickerstreak@30: if value > max then flickerstreak@30: value = max flickerstreak@30: elseif value < min then flickerstreak@30: value = min flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if sliderFrame.parent.sliderIsPercent then flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.0f%%", value * 100)) flickerstreak@30: else flickerstreak@30: if step < 0.1 then flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.2f", value)) flickerstreak@30: elseif step < 1 then flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.1f", value)) flickerstreak@30: else flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.0f", value)) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: local function onEnter() flickerstreak@30: StopCounting(self, sliderFrame.level) flickerstreak@30: showGameTooltip(sliderFrame.parent) flickerstreak@30: end flickerstreak@30: local function onLeave() flickerstreak@30: GameTooltip:Hide() flickerstreak@30: end flickerstreak@30: sliderFrame:SetScript("OnEnter", onEnter) flickerstreak@30: sliderFrame:SetScript("OnLeave", function() flickerstreak@30: GameTooltip:Hide() flickerstreak@30: if changed then flickerstreak@30: local parent = sliderFrame.parent flickerstreak@30: local sliderFunc = parent.sliderFunc flickerstreak@30: for i = 1, sliderFrame.level - 1 do flickerstreak@30: Refresh(self, levels[i]) flickerstreak@30: end flickerstreak@30: local newParent flickerstreak@30: for _,button in ipairs(levels[sliderFrame.level-1].buttons) do flickerstreak@30: if button.sliderFunc == sliderFunc then flickerstreak@30: newParent = button flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if newParent then flickerstreak@30: OpenSlider(self, newParent) flickerstreak@30: else flickerstreak@30: sliderFrame:Hide() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnEnter", onEnter) flickerstreak@30: editBox:SetScript("OnLeave", onLeave) flickerstreak@30: slider:SetScript("OnMouseDown", function() flickerstreak@30: sliderFrame.mouseDown = true flickerstreak@30: GameTooltip:Hide() flickerstreak@30: end) flickerstreak@30: slider:SetScript("OnMouseUp", function() flickerstreak@30: sliderFrame.mouseDown = false flickerstreak@30: if changed--[[ and not inside]] then flickerstreak@30: local parent = sliderFrame.parent flickerstreak@30: local sliderFunc = parent.sliderFunc flickerstreak@30: for i = 1, sliderFrame.level - 1 do flickerstreak@30: Refresh(self, levels[i]) flickerstreak@30: end flickerstreak@30: local newParent flickerstreak@30: for _,button in ipairs(levels[sliderFrame.level-1].buttons) do flickerstreak@30: if button.sliderFunc == sliderFunc then flickerstreak@30: newParent = button flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if newParent then flickerstreak@30: OpenSlider(self, newParent) flickerstreak@30: else flickerstreak@30: sliderFrame:Hide() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if inside then flickerstreak@30: showGameTooltip(sliderFrame.parent) flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: slider:SetScript("OnEnter", function() flickerstreak@30: inside = true flickerstreak@30: StopCounting(self, sliderFrame.level) flickerstreak@30: showGameTooltip(sliderFrame.parent) flickerstreak@30: end) flickerstreak@30: slider:SetScript("OnLeave", function() flickerstreak@30: inside = false flickerstreak@30: GameTooltip:Hide() flickerstreak@30: if changed and not sliderFrame.mouseDown then flickerstreak@30: local parent = sliderFrame.parent flickerstreak@30: local sliderFunc = parent.sliderFunc flickerstreak@30: for i = 1, sliderFrame.level - 1 do flickerstreak@30: Refresh(self, levels[i]) flickerstreak@30: end flickerstreak@30: local newParent flickerstreak@30: for _,button in ipairs(levels[sliderFrame.level-1].buttons) do flickerstreak@30: if button.sliderFunc == sliderFunc then flickerstreak@30: newParent = button flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if newParent then flickerstreak@30: OpenSlider(self, newParent) flickerstreak@30: else flickerstreak@30: sliderFrame:Hide() flickerstreak@30: end flickerstreak@30: flickerstreak@30: changed = false flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: sliderFrame:SetScript("OnMouseWheel", function(t, a1) flickerstreak@30: local arg1 = a1 or arg1 flickerstreak@30: local up = arg1 > 0 flickerstreak@30: flickerstreak@30: local min = sliderFrame.parent.sliderMin or 0 flickerstreak@30: local max = sliderFrame.parent.sliderMax or 1 flickerstreak@30: local step = sliderFrame.parent.sliderStep or (max - min) / 100 flickerstreak@30: if step <= 0 then flickerstreak@30: step = (max - min) / 100 flickerstreak@30: end flickerstreak@30: flickerstreak@30: local value = (1 - slider:GetValue()) * (max - min) + min flickerstreak@30: if up then flickerstreak@30: value = value + step flickerstreak@30: else flickerstreak@30: value = value - step flickerstreak@30: end flickerstreak@30: if value > max then flickerstreak@30: value = max flickerstreak@30: elseif value < min then flickerstreak@30: value = min flickerstreak@30: end flickerstreak@30: sliderFrame.fineStep = true flickerstreak@30: if max<=min then flickerstreak@30: slider:SetValue(0) flickerstreak@30: else flickerstreak@30: slider:SetValue(1 - (value - min) / (max - min)) flickerstreak@30: end flickerstreak@30: sliderFrame.fineStep = nil flickerstreak@30: end) flickerstreak@30: slider:SetScript("OnMouseWheel", sliderFrame:GetScript("OnMouseWheel")) flickerstreak@30: editBox:SetScript("OnEnterPressed", function(t, a1) flickerstreak@30: local value = editBox:GetNumber() flickerstreak@30: flickerstreak@30: if sliderFrame.parent.sliderIsPercent then flickerstreak@30: value = value / 100 flickerstreak@30: end flickerstreak@30: flickerstreak@30: local min = sliderFrame.parent.sliderMin or 0 flickerstreak@30: local max = sliderFrame.parent.sliderMax or 1 flickerstreak@30: flickerstreak@30: if value > max then flickerstreak@30: value = max flickerstreak@30: elseif value < min then flickerstreak@30: value = min flickerstreak@30: end flickerstreak@30: sliderFrame.fineStep = true flickerstreak@30: if max <= min then flickerstreak@30: slider:SetValue(0) flickerstreak@30: else flickerstreak@30: slider:SetValue(1 - (value - min) / (max - min)) flickerstreak@30: end flickerstreak@30: sliderFrame.fineStep = nil flickerstreak@30: flickerstreak@30: StartCounting(self, sliderFrame.level) flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnEscapePressed", function() flickerstreak@30: self:Close(sliderFrame.level) flickerstreak@30: StartCounting(self, sliderFrame.level) flickerstreak@30: end) flickerstreak@30: editBox:SetAutoFocus(false) flickerstreak@30: end flickerstreak@30: sliderFrame.parent = parent flickerstreak@30: sliderFrame.level = parent.level.num + 1 flickerstreak@30: sliderFrame.parentValue = parent.level.value flickerstreak@30: sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) flickerstreak@30: sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) flickerstreak@30: sliderFrame.currentText:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) flickerstreak@30: sliderFrame.currentText:ClearFocus() flickerstreak@30: sliderFrame.changing = true flickerstreak@30: if not parent.sliderMin or not parent.sliderMax then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: flickerstreak@30: if parent.arrow then flickerstreak@30: -- parent.arrow:SetVertexColor(0.2, 0.6, 0) flickerstreak@30: -- parent.arrow:SetHeight(24) flickerstreak@30: -- parent.arrow:SetWidth(24) flickerstreak@30: parent.selected = true flickerstreak@30: parent.highlight:Show() flickerstreak@30: end flickerstreak@30: flickerstreak@30: sliderFrame:SetClampedToScreen(false) flickerstreak@30: if not parent.sliderValue then flickerstreak@30: parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2 flickerstreak@30: end flickerstreak@30: if parent.sliderMax <= parent.sliderMin then flickerstreak@30: sliderFrame.slider:SetValue(0) flickerstreak@30: else flickerstreak@30: sliderFrame.slider:SetValue(1 - (parent.sliderValue - parent.sliderMin) / (parent.sliderMax - parent.sliderMin)) flickerstreak@30: end flickerstreak@30: sliderFrame.changing = false flickerstreak@30: sliderFrame.bottomText:SetText(parent.sliderMinText or "0") flickerstreak@30: sliderFrame.topText:SetText(parent.sliderMaxText or "1") flickerstreak@30: local text flickerstreak@30: if parent.sliderFunc and not parent.fromAceOptions then flickerstreak@30: text = parent.sliderFunc(getArgs(parent, 'sliderArg', 1, parent.sliderValue)) flickerstreak@30: end flickerstreak@30: if type(text) == "number" or type(text) == "string" then flickerstreak@30: sliderFrame.currentText:SetText(text) flickerstreak@30: elseif parent.sliderIsPercent then flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.0f%%", parent.sliderValue * 100)) flickerstreak@30: else flickerstreak@30: if parent.sliderStep < 0.1 then flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.2f", parent.sliderValue)) flickerstreak@30: elseif parent.sliderStep < 1 then flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.1f", parent.sliderValue)) flickerstreak@30: else flickerstreak@30: sliderFrame.currentText:SetText(string.format("%.0f", parent.sliderValue)) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: flickerstreak@30: sliderFrame.lastValue = parent.sliderValue flickerstreak@30: flickerstreak@30: local level = parent.level flickerstreak@30: sliderFrame:Show() flickerstreak@30: sliderFrame:ClearAllPoints() flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local dirty flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if sliderFrame:GetRight() > GetScreenWidth() then flickerstreak@30: level.lastDirection = "LEFT" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: elseif sliderFrame:GetLeft() < 0 then flickerstreak@30: level.lastDirection = "RIGHT" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: if sliderFrame:GetBottom() < 0 then flickerstreak@30: level.lastVDirection = "UP" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: elseif sliderFrame:GetTop() > GetScreenWidth() then flickerstreak@30: level.lastVDirection = "DOWN" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: if dirty then flickerstreak@30: sliderFrame:ClearAllPoints() flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() flickerstreak@30: sliderFrame:ClearAllPoints() flickerstreak@30: sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) flickerstreak@30: if mod(level.num, 5) == 0 then flickerstreak@30: local left, bottom = level:GetLeft(), level:GetBottom() flickerstreak@30: level:ClearAllPoints() flickerstreak@30: level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) flickerstreak@30: end flickerstreak@30: sliderFrame:SetClampedToScreen(true) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function OpenEditBox(self, parent) flickerstreak@30: if not editBoxFrame then flickerstreak@30: editBoxFrame = CreateFrame("Frame", nil, nil) flickerstreak@30: editBoxFrame:SetWidth(200) flickerstreak@30: editBoxFrame:SetHeight(40) flickerstreak@30: editBoxFrame:SetScale(UIParent:GetScale()) flickerstreak@30: editBoxFrame:SetBackdrop(tmp( flickerstreak@30: 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", flickerstreak@30: 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", flickerstreak@30: 'tile', true, flickerstreak@30: 'insets', tmp2( flickerstreak@30: 'left', 5, flickerstreak@30: 'right', 5, flickerstreak@30: 'top', 5, flickerstreak@30: 'bottom', 5 flickerstreak@30: ), flickerstreak@30: 'tileSize', 16, flickerstreak@30: 'edgeSize', 16 flickerstreak@30: )) flickerstreak@30: editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG") flickerstreak@30: if editBoxFrame.SetTopLevel then flickerstreak@30: editBoxFrame:SetTopLevel(true) flickerstreak@30: end flickerstreak@30: editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) flickerstreak@30: editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) flickerstreak@30: editBoxFrame:EnableMouse(true) flickerstreak@30: editBoxFrame:EnableMouseWheel(true) flickerstreak@30: editBoxFrame:Hide() flickerstreak@30: editBoxFrame:SetPoint("CENTER", UIParent, "CENTER") flickerstreak@30: flickerstreak@30: local editBox = CreateFrame("EditBox", nil, editBoxFrame) flickerstreak@30: editBoxFrame.editBox = editBox flickerstreak@30: editBox:SetFontObject(ChatFontNormal) flickerstreak@30: editBox:SetWidth(160) flickerstreak@30: editBox:SetHeight(13) flickerstreak@30: editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0) flickerstreak@30: flickerstreak@30: local left = editBox:CreateTexture(nil, "BACKGROUND") flickerstreak@30: left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") flickerstreak@30: left:SetTexCoord(0, 100 / 256, 0, 1) flickerstreak@30: left:SetWidth(100) flickerstreak@30: left:SetHeight(32) flickerstreak@30: left:SetPoint("LEFT", editBox, "LEFT", -10, 0) flickerstreak@30: local right = editBox:CreateTexture(nil, "BACKGROUND") flickerstreak@30: right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") flickerstreak@30: right:SetTexCoord(156/256, 1, 0, 1) flickerstreak@30: right:SetWidth(100) flickerstreak@30: right:SetHeight(32) flickerstreak@30: right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) flickerstreak@30: flickerstreak@30: editBox:SetScript("OnEnterPressed", function() flickerstreak@30: if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then flickerstreak@30: local t = editBox.realText or editBox:GetText() or "" flickerstreak@30: local result = editBoxFrame.parent.editBoxValidateFunc(getArgs(editBoxFrame.parent, 'editBoxValidateArg', 1, t)) flickerstreak@30: if not result then flickerstreak@30: UIErrorsFrame:AddMessage(VALIDATION_ERROR, 1, 0, 0) flickerstreak@30: return flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then flickerstreak@30: local t flickerstreak@30: if editBox.realText ~= "NONE" then flickerstreak@30: t = editBox.realText or editBox:GetText() or "" flickerstreak@30: end flickerstreak@30: editBoxFrame.parent.editBoxFunc(getArgs(editBoxFrame.parent, 'editBoxArg', 1, t)) flickerstreak@30: end flickerstreak@30: self:Close(editBoxFrame.level) flickerstreak@30: for i = 1, editBoxFrame.level - 1 do flickerstreak@30: Refresh(self, levels[i]) flickerstreak@30: end flickerstreak@30: StartCounting(self, editBoxFrame.level-1) flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnEscapePressed", function() flickerstreak@30: self:Close(editBoxFrame.level) flickerstreak@30: StartCounting(self, editBoxFrame.level-1) flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnReceiveDrag", function(this) flickerstreak@30: if GetCursorInfo then flickerstreak@30: local type, alpha, bravo = GetCursorInfo() flickerstreak@30: local text flickerstreak@30: if type == "spell" then flickerstreak@30: text = GetSpellName(alpha, bravo) flickerstreak@30: elseif type == "item" then flickerstreak@30: text = bravo flickerstreak@30: end flickerstreak@30: if not text then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: ClearCursor() flickerstreak@30: editBox:SetText(text) flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: local changing = false flickerstreak@30: local skipNext = false flickerstreak@30: flickerstreak@30: function editBox:SpecialSetText(text) flickerstreak@30: local oldText = editBox:GetText() or "" flickerstreak@30: if not text then flickerstreak@30: text = "" flickerstreak@30: end flickerstreak@30: if text ~= oldText then flickerstreak@30: changing = true flickerstreak@30: self:SetText(tostring(text)) flickerstreak@30: changing = false flickerstreak@30: skipNext = true flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: editBox:SetScript("OnTextChanged", function() flickerstreak@30: if skipNext then flickerstreak@30: skipNext = false flickerstreak@30: elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then flickerstreak@30: local t flickerstreak@30: if editBox.realText ~= "NONE" then flickerstreak@30: t = editBox.realText or editBox:GetText() or "" flickerstreak@30: end flickerstreak@30: local text = editBoxFrame.parent.editBoxChangeFunc(getArgs(editBoxFrame.parent, 'editBoxChangeArg', 1, t)) flickerstreak@30: if text then flickerstreak@30: editBox:SpecialSetText(text) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: editBoxFrame:SetScript("OnEnter", function() flickerstreak@30: StopCounting(self, editBoxFrame.level) flickerstreak@30: showGameTooltip(editBoxFrame.parent) flickerstreak@30: end) flickerstreak@30: editBoxFrame:SetScript("OnLeave", function() flickerstreak@30: GameTooltip:Hide() flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnEnter", function() flickerstreak@30: StopCounting(self, editBoxFrame.level) flickerstreak@30: showGameTooltip(editBoxFrame.parent) flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnLeave", function() flickerstreak@30: GameTooltip:Hide() flickerstreak@30: end) flickerstreak@30: editBoxFrame:SetScript("OnKeyDown", function(this, a1) flickerstreak@30: if not editBox.keybinding then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: local arg1 = a1 or arg1 flickerstreak@30: local screenshotKey = GetBindingKey("SCREENSHOT") flickerstreak@30: if screenshotKey and arg1 == screenshotKey then flickerstreak@30: Screenshot() flickerstreak@30: return flickerstreak@30: end flickerstreak@30: flickerstreak@30: if arg1 == "LeftButton" then flickerstreak@30: arg1 = "BUTTON1" flickerstreak@30: elseif arg1 == "RightButton" then flickerstreak@30: arg1 = "BUTTON2" flickerstreak@30: elseif arg1 == "MiddleButton" then flickerstreak@30: arg1 = "BUTTON3" flickerstreak@30: elseif arg1 == "Button4" then flickerstreak@30: arg1 = "BUTTON4" flickerstreak@30: elseif arg1 == "Button5" then flickerstreak@30: arg1 = "BUTTON5" flickerstreak@30: end flickerstreak@30: if arg1 == "UNKNOWN" then flickerstreak@30: return flickerstreak@30: elseif arg1 == "SHIFT" or arg1 == "CTRL" or arg1 == "ALT" then flickerstreak@30: return flickerstreak@30: elseif arg1 == "ENTER" then flickerstreak@30: if editBox.keybindingOnly and not editBox.keybindingOnly[editBox.realText] then flickerstreak@30: return editBox:GetScript("OnEscapePressed")() flickerstreak@30: elseif editBox.keybindingExcept and editBox.keybindingExcept[editBox.realText] then flickerstreak@30: return editBox:GetScript("OnEscapePressed")() flickerstreak@30: else flickerstreak@30: return editBox:GetScript("OnEnterPressed")() flickerstreak@30: end flickerstreak@30: elseif arg1 == "ESCAPE" then flickerstreak@30: if editBox.realText == "NONE" then flickerstreak@30: return editBox:GetScript("OnEscapePressed")() flickerstreak@30: else flickerstreak@30: editBox:SpecialSetText(NONE or "NONE") flickerstreak@30: editBox.realText = "NONE" flickerstreak@30: return flickerstreak@30: end flickerstreak@30: elseif editBox.keybindingOnly and not editBox.keybindingOnly[arg1] then flickerstreak@30: return flickerstreak@30: elseif editBox.keybindingExcept and editBox.keybindingExcept[arg1] then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: local s = GetBindingText(arg1, "KEY_") flickerstreak@30: if s == "BUTTON1" then flickerstreak@30: s = KEY_BUTTON1 flickerstreak@30: elseif s == "BUTTON2" then flickerstreak@30: s = KEY_BUTTON2 flickerstreak@30: end flickerstreak@30: local real = arg1 flickerstreak@30: if IsShiftKeyDown() then flickerstreak@30: s = "Shift-" .. s flickerstreak@30: real = "SHIFT-" .. real flickerstreak@30: end flickerstreak@30: if IsControlKeyDown() then flickerstreak@30: s = "Ctrl-" .. s flickerstreak@30: real = "CTRL-" .. real flickerstreak@30: end flickerstreak@30: if IsAltKeyDown() then flickerstreak@30: s = "Alt-" .. s flickerstreak@30: real = "ALT-" .. real flickerstreak@30: end flickerstreak@30: if editBox:GetText() ~= s then flickerstreak@30: editBox:SpecialSetText("-") flickerstreak@30: editBox:SpecialSetText(s) flickerstreak@30: editBox.realText = real flickerstreak@30: return editBox:GetScript("OnTextChanged")() flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: editBoxFrame:SetScript("OnMouseDown", editBoxFrame:GetScript("OnKeyDown")) flickerstreak@30: editBox:SetScript("OnMouseDown", function(this, ...) flickerstreak@30: if GetCursorInfo and (CursorHasItem() or CursorHasSpell()) then flickerstreak@30: return editBox:GetScript("OnReceiveDrag")(this, ...) flickerstreak@30: end flickerstreak@30: return editBoxFrame:GetScript("OnKeyDown")(this, ...) flickerstreak@30: end) flickerstreak@30: editBoxFrame:SetScript("OnMouseWheel", function(t, a1) flickerstreak@30: local arg1 = a1 or arg1 flickerstreak@30: local up = arg1 > 0 flickerstreak@30: arg1 = up and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" flickerstreak@30: return editBoxFrame:GetScript("OnKeyDown")(t or this, arg1) flickerstreak@30: end) flickerstreak@30: editBox:SetScript("OnMouseWheel", editBoxFrame:GetScript("OnMouseWheel")) flickerstreak@30: end flickerstreak@30: editBoxFrame.parent = parent flickerstreak@30: editBoxFrame.level = parent.level.num + 1 flickerstreak@30: editBoxFrame.parentValue = parent.level.value flickerstreak@30: editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) flickerstreak@30: editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1) flickerstreak@30: editBoxFrame.editBox.realText = nil flickerstreak@30: editBoxFrame:SetClampedToScreen(false) flickerstreak@30: flickerstreak@30: editBoxFrame.editBox:SpecialSetText("") flickerstreak@30: if parent.editBoxIsKeybinding then flickerstreak@30: local s = parent.editBoxText flickerstreak@30: if s == "" then flickerstreak@30: s = "NONE" flickerstreak@30: end flickerstreak@30: editBoxFrame.editBox.realText = s flickerstreak@30: if s and s ~= "NONE" then flickerstreak@30: local alpha,bravo = s:match("^(.+)%-(.+)$") flickerstreak@30: if not bravo then flickerstreak@30: alpha = nil flickerstreak@30: bravo = s flickerstreak@30: end flickerstreak@30: bravo = GetBindingText(bravo, "KEY_") flickerstreak@30: if alpha then flickerstreak@30: editBoxFrame.editBox:SpecialSetText(alpha:upper() .. "-" .. bravo) flickerstreak@30: else flickerstreak@30: editBoxFrame.editBox:SpecialSetText(bravo) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: editBoxFrame.editBox:SpecialSetText(NONE or "NONE") flickerstreak@30: end flickerstreak@30: else flickerstreak@30: editBoxFrame.editBox:SpecialSetText(parent.editBoxText) flickerstreak@30: end flickerstreak@30: flickerstreak@30: editBoxFrame.editBox.keybinding = parent.editBoxIsKeybinding flickerstreak@30: editBoxFrame.editBox.keybindingOnly = parent.editBoxKeybindingOnly flickerstreak@30: editBoxFrame.editBox.keybindingExcept = parent.editBoxKeybindingExcept flickerstreak@30: editBoxFrame.editBox:EnableKeyboard(not parent.editBoxIsKeybinding) flickerstreak@30: editBoxFrame:EnableKeyboard(parent.editBoxIsKeybinding) flickerstreak@30: flickerstreak@30: if parent.arrow then flickerstreak@30: -- parent.arrow:SetVertexColor(0.2, 0.6, 0) flickerstreak@30: -- parent.arrow:SetHeight(24) flickerstreak@30: -- parent.arrow:SetWidth(24) flickerstreak@30: parent.selected = true flickerstreak@30: parent.highlight:Show() flickerstreak@30: end flickerstreak@30: flickerstreak@30: local level = parent.level flickerstreak@30: editBoxFrame:Show() flickerstreak@30: editBoxFrame:ClearAllPoints() flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local dirty flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if editBoxFrame:GetRight() > GetScreenWidth() then flickerstreak@30: level.lastDirection = "LEFT" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: elseif editBoxFrame:GetLeft() < 0 then flickerstreak@30: level.lastDirection = "RIGHT" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: if editBoxFrame:GetBottom() < 0 then flickerstreak@30: level.lastVDirection = "UP" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: elseif editBoxFrame:GetTop() > GetScreenWidth() then flickerstreak@30: level.lastVDirection = "DOWN" flickerstreak@30: dirty = true flickerstreak@30: end flickerstreak@30: if dirty then flickerstreak@30: editBoxFrame:ClearAllPoints() flickerstreak@30: if level.lastDirection == "RIGHT" then flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) flickerstreak@30: else flickerstreak@30: editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: if level.lastVDirection == "DOWN" then flickerstreak@30: editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) flickerstreak@30: else flickerstreak@30: editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom() flickerstreak@30: editBoxFrame:ClearAllPoints() flickerstreak@30: editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) flickerstreak@30: if mod(level.num, 5) == 0 then flickerstreak@30: local left, bottom = level:GetLeft(), level:GetBottom() flickerstreak@30: level:ClearAllPoints() flickerstreak@30: level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) flickerstreak@30: end flickerstreak@30: editBoxFrame:SetClampedToScreen(true) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:EncodeKeybinding(text) flickerstreak@30: if text == nil or text == "NONE" then flickerstreak@30: return nil flickerstreak@30: end flickerstreak@30: text = tostring(text):upper() flickerstreak@30: local shift, ctrl, alt flickerstreak@30: local modifier flickerstreak@30: while true do flickerstreak@30: if text == "-" then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: modifier, text = strsplit('-', text, 2) flickerstreak@30: if text then flickerstreak@30: if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: if modifier == "SHIFT" then flickerstreak@30: if shift then flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: shift = true flickerstreak@30: end flickerstreak@30: if modifier == "CTRL" then flickerstreak@30: if ctrl then flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: ctrl = true flickerstreak@30: end flickerstreak@30: if modifier == "ALT" then flickerstreak@30: if alt then flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: alt = true flickerstreak@30: end flickerstreak@30: else flickerstreak@30: text = modifier flickerstreak@30: break flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:len() == 0 or text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] and text ~= "BUTTON1" and text ~= "BUTTON2" then flickerstreak@30: return false flickerstreak@30: end flickerstreak@30: local s = GetBindingText(text, "KEY_") flickerstreak@30: if s == "BUTTON1" then flickerstreak@30: s = KEY_BUTTON1 flickerstreak@30: elseif s == "BUTTON2" then flickerstreak@30: s = KEY_BUTTON2 flickerstreak@30: end flickerstreak@30: if shift then flickerstreak@30: s = "Shift-" .. s flickerstreak@30: end flickerstreak@30: if ctrl then flickerstreak@30: s = "Ctrl-" .. s flickerstreak@30: end flickerstreak@30: if alt then flickerstreak@30: s = "Alt-" .. s flickerstreak@30: end flickerstreak@30: return s flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:IsOpen(parent) flickerstreak@30: self:argCheck(parent, 2, "table", "string", "nil") flickerstreak@30: return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent()) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:GetOpenedParent() flickerstreak@30: return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent()) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY) flickerstreak@30: self:Close(level) flickerstreak@30: if DewdropLib then flickerstreak@30: local d = DewdropLib:GetInstance('1.0') flickerstreak@30: local ret, val = pcall(d, IsOpen, d) flickerstreak@30: if ret and val then flickerstreak@30: DewdropLib:GetInstance('1.0'):Close() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if type(parent) == "table" then flickerstreak@30: parent:GetCenter() flickerstreak@30: end flickerstreak@30: local frame = AcquireLevel(self, level) flickerstreak@30: if level == 1 then flickerstreak@30: frame.lastDirection = "RIGHT" flickerstreak@30: frame.lastVDirection = "DOWN" flickerstreak@30: else flickerstreak@30: frame.lastDirection = levels[level - 1].lastDirection flickerstreak@30: frame.lastVDirection = levels[level - 1].lastVDirection flickerstreak@30: end flickerstreak@30: frame:SetFrameStrata("FULLSCREEN_DIALOG") flickerstreak@30: frame:ClearAllPoints() flickerstreak@30: frame.parent = parent flickerstreak@30: frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) flickerstreak@30: frame:Show() flickerstreak@30: if level == 1 then flickerstreak@30: baseFunc = func flickerstreak@30: end flickerstreak@30: levels[level].value = value flickerstreak@30: -- levels[level].parentText = parent.text and parent.text:GetText() or nil flickerstreak@30: -- levels[level].parentTooltipTitle = parent.tooltipTitle flickerstreak@30: -- levels[level].parentTooltipText = parent.tooltipText flickerstreak@30: -- levels[level].parentTooltipFunc = parent.tooltipFunc flickerstreak@30: if type(parent) == "table" and parent.arrow then flickerstreak@30: -- parent.arrow:SetVertexColor(0.2, 0.6, 0) flickerstreak@30: -- parent.arrow:SetHeight(24) flickerstreak@30: -- parent.arrow:SetWidth(24) flickerstreak@30: parent.selected = true flickerstreak@30: parent.highlight:Show() flickerstreak@30: end flickerstreak@30: relativePoint = relativePoint or point flickerstreak@30: Refresh(self, levels[level]) flickerstreak@30: if point or (cursorX and cursorY) then flickerstreak@30: frame:ClearAllPoints() flickerstreak@30: if cursorX and cursorY then flickerstreak@30: local curX, curY = GetScaledCursorPosition() flickerstreak@30: if curY < GetScreenHeight() / 2 then flickerstreak@30: point, relativePoint = "BOTTOM", "BOTTOM" flickerstreak@30: else flickerstreak@30: point, relativePoint = "TOP", "TOP" flickerstreak@30: end flickerstreak@30: if curX < GetScreenWidth() / 2 then flickerstreak@30: point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT" flickerstreak@30: else flickerstreak@30: point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT" flickerstreak@30: end flickerstreak@30: end flickerstreak@30: frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint) flickerstreak@30: if cursorX and cursorY then flickerstreak@30: local left = frame:GetLeft() flickerstreak@30: local width = frame:GetWidth() flickerstreak@30: local bottom = frame:GetBottom() flickerstreak@30: local height = frame:GetHeight() flickerstreak@30: local curX, curY = GetScaledCursorPosition() flickerstreak@30: frame:ClearAllPoints() flickerstreak@30: relativePoint = relativePoint or point flickerstreak@30: if point == "BOTTOM" or point == "TOP" then flickerstreak@30: if curX < GetScreenWidth() / 2 then flickerstreak@30: point = point .. "LEFT" flickerstreak@30: else flickerstreak@30: point = point .. "RIGHT" flickerstreak@30: end flickerstreak@30: elseif point == "CENTER" then flickerstreak@30: if curX < GetScreenWidth() / 2 then flickerstreak@30: point = "LEFT" flickerstreak@30: else flickerstreak@30: point = "RIGHT" flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local xOffset, yOffset = 0, 0 flickerstreak@30: if curY > GetScreenHeight() / 2 then flickerstreak@30: yOffset = -height flickerstreak@30: end flickerstreak@30: if curX > GetScreenWidth() / 2 then flickerstreak@30: xOffset = -width flickerstreak@30: end flickerstreak@30: frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left + xOffset, curY - bottom + yOffset) flickerstreak@30: if level == 1 then flickerstreak@30: frame.lastDirection = "RIGHT" flickerstreak@30: end flickerstreak@30: elseif cursorX then flickerstreak@30: local left = frame:GetLeft() flickerstreak@30: local width = frame:GetWidth() flickerstreak@30: local curX, curY = GetScaledCursorPosition() flickerstreak@30: frame:ClearAllPoints() flickerstreak@30: relativePoint = relativePoint or point flickerstreak@30: if point == "BOTTOM" or point == "TOP" then flickerstreak@30: if curX < GetScreenWidth() / 2 then flickerstreak@30: point = point .. "LEFT" flickerstreak@30: else flickerstreak@30: point = point .. "RIGHT" flickerstreak@30: end flickerstreak@30: elseif point == "CENTER" then flickerstreak@30: if curX < GetScreenWidth() / 2 then flickerstreak@30: point = "LEFT" flickerstreak@30: else flickerstreak@30: point = "RIGHT" flickerstreak@30: end flickerstreak@30: end flickerstreak@30: frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left - width / 2, 0) flickerstreak@30: if level == 1 then flickerstreak@30: frame.lastDirection = "RIGHT" flickerstreak@30: end flickerstreak@30: elseif cursorY then flickerstreak@30: local bottom = frame:GetBottom() flickerstreak@30: local height = frame:GetHeight() flickerstreak@30: local curX, curY = GetScaledCursorPosition() flickerstreak@30: frame:ClearAllPoints() flickerstreak@30: relativePoint = relativePoint or point flickerstreak@30: if point == "LEFT" or point == "RIGHT" then flickerstreak@30: if curX < GetScreenHeight() / 2 then flickerstreak@30: point = point .. "BOTTOM" flickerstreak@30: else flickerstreak@30: point = point .. "TOP" flickerstreak@30: end flickerstreak@30: elseif point == "CENTER" then flickerstreak@30: if curX < GetScreenHeight() / 2 then flickerstreak@30: point = "BOTTOM" flickerstreak@30: else flickerstreak@30: point = "TOP" flickerstreak@30: end flickerstreak@30: end flickerstreak@30: frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, 0, curY - bottom - height / 2) flickerstreak@30: if level == 1 then flickerstreak@30: frame.lastDirection = "DOWN" flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then flickerstreak@30: if frame:GetBottom() < 0 then flickerstreak@30: local point, parent, relativePoint, x, y = frame:GetPoint(1) flickerstreak@30: local change = GetScreenHeight() - frame:GetTop() flickerstreak@30: local otherChange = -frame:GetBottom() flickerstreak@30: if otherChange < change then flickerstreak@30: change = otherChange flickerstreak@30: end flickerstreak@30: frame:SetPoint(point, parent, relativePoint, x, y + change) flickerstreak@30: elseif frame:GetTop() > GetScreenHeight() then flickerstreak@30: local point, parent, relativePoint, x, y = frame:GetPoint(1) flickerstreak@30: local change = GetScreenHeight() - frame:GetTop() flickerstreak@30: local otherChange = -frame:GetBottom() flickerstreak@30: if otherChange < change then flickerstreak@30: change = otherChange flickerstreak@30: end flickerstreak@30: frame:SetPoint(point, parent, relativePoint, x, y + change) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: CheckDualMonitor(self, frame) flickerstreak@30: frame:SetClampedToScreen(true) flickerstreak@30: frame:SetClampedToScreen(false) flickerstreak@30: StartCounting(self, level) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:IsRegistered(parent) flickerstreak@30: self:argCheck(parent, 2, "table", "string") flickerstreak@30: return not not self.registry[parent] flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:Register(parent, ...) flickerstreak@30: self:argCheck(parent, 2, "table", "string") flickerstreak@30: if self.registry[parent] then flickerstreak@30: self:Unregister(parent) flickerstreak@30: end flickerstreak@30: local info = new(...) flickerstreak@30: if type(info.children) == "table" then flickerstreak@30: local err, position = validateOptions(info.children) flickerstreak@30: flickerstreak@30: if err then flickerstreak@30: if position then flickerstreak@30: Dewdrop:error(position .. ": " .. err) flickerstreak@30: else flickerstreak@30: Dewdrop:error(err) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self.registry[parent] = info flickerstreak@30: if not info.dontHook and not self.onceRegistered[parent] and type(parent) == "table" then flickerstreak@30: if parent:HasScript("OnMouseUp") then flickerstreak@30: local script = parent:GetScript("OnMouseUp") flickerstreak@30: parent:SetScript("OnMouseUp", function(this, ...) flickerstreak@30: if script then flickerstreak@30: script(this, ...) flickerstreak@30: end flickerstreak@30: if arg1 == "RightButton" and self.registry[parent] then flickerstreak@30: if self:IsOpen(parent) then flickerstreak@30: self:Close() flickerstreak@30: else flickerstreak@30: self:Open(parent) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: end flickerstreak@30: if parent:HasScript("OnMouseDown") then flickerstreak@30: local script = parent:GetScript("OnMouseDown") flickerstreak@30: parent:SetScript("OnMouseDown", function(this, ...) flickerstreak@30: if script then flickerstreak@30: script(this, ...) flickerstreak@30: end flickerstreak@30: if self.registry[parent] then flickerstreak@30: self:Close() flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self.onceRegistered[parent] = true flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:Unregister(parent) flickerstreak@30: self:argCheck(parent, 2, "table", "string") flickerstreak@30: self.registry[parent] = nil flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:Open(parent, ...) flickerstreak@30: self:argCheck(parent, 2, "table", "string") flickerstreak@30: local info flickerstreak@30: local k1 = ... flickerstreak@30: if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then flickerstreak@30: info = tmp(select(2, ...)) flickerstreak@30: for k,v in pairs(self.registry[k1]) do flickerstreak@30: if info[k] == nil then flickerstreak@30: info[k] = v flickerstreak@30: end flickerstreak@30: end flickerstreak@30: else flickerstreak@30: info = tmp(...) flickerstreak@30: if self.registry[parent] then flickerstreak@30: for k,v in pairs(self.registry[parent]) do flickerstreak@30: if info[k] == nil then flickerstreak@30: info[k] = v flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local point = info.point flickerstreak@30: local relativePoint = info.relativePoint flickerstreak@30: local cursorX = info.cursorX flickerstreak@30: local cursorY = info.cursorY flickerstreak@30: if type(point) == "function" then flickerstreak@30: local b flickerstreak@30: point, b = point(parent) flickerstreak@30: if b then flickerstreak@30: relativePoint = b flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if type(relativePoint) == "function" then flickerstreak@30: relativePoint = relativePoint(parent) flickerstreak@30: end flickerstreak@30: Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Clear(self, level) flickerstreak@30: if level then flickerstreak@30: if level.buttons then flickerstreak@30: for i = #level.buttons, 1, -1 do flickerstreak@30: ReleaseButton(self, level, i) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:Close(level) flickerstreak@30: if DropDownList1:IsShown() then flickerstreak@30: DropDownList1:Hide() flickerstreak@30: end flickerstreak@30: if DewdropLib then flickerstreak@30: local d = DewdropLib:GetInstance('1.0') flickerstreak@30: local ret, val = pcall(d, IsOpen, d) flickerstreak@30: if ret and val then flickerstreak@30: DewdropLib:GetInstance('1.0'):Close() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: self:argCheck(level, 2, "number", "nil") flickerstreak@30: if not level then flickerstreak@30: level = 1 flickerstreak@30: end flickerstreak@30: if level == 1 and levels[level] then flickerstreak@30: levels[level].parented = false flickerstreak@30: end flickerstreak@30: if level > 1 and levels[level-1].buttons then flickerstreak@30: local buttons = levels[level-1].buttons flickerstreak@30: for _,button in ipairs(buttons) do flickerstreak@30: -- button.arrow:SetWidth(16) flickerstreak@30: -- button.arrow:SetHeight(16) flickerstreak@30: button.selected = nil flickerstreak@30: button.highlight:Hide() flickerstreak@30: -- button.arrow:SetVertexColor(1, 1, 1) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if sliderFrame and sliderFrame.level >= level then flickerstreak@30: sliderFrame:Hide() flickerstreak@30: end flickerstreak@30: if editBoxFrame and editBoxFrame.level >= level then flickerstreak@30: editBoxFrame:Hide() flickerstreak@30: end flickerstreak@30: for i = level, #levels do flickerstreak@30: Clear(self, levels[level]) flickerstreak@30: levels[i]:Hide() flickerstreak@30: levels[i]:ClearAllPoints() flickerstreak@30: levels[i]:SetPoint("CENTER", UIParent, "CENTER") flickerstreak@30: levels[i].value = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:AddSeparator(level) flickerstreak@30: level = levels[level or currentLevel] flickerstreak@30: if not level or not level.buttons then return; end flickerstreak@30: flickerstreak@30: local prevbutton = level.buttons[#level.buttons] flickerstreak@30: if not prevbutton then return; end flickerstreak@30: flickerstreak@30: if prevbutton.disabled and prevbutton.text:GetText() == "" then flickerstreak@30: return flickerstreak@30: end flickerstreak@30: self:AddLine("text", "", "disabled", true) flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:AddLine(...) flickerstreak@30: local info = tmp(...) flickerstreak@30: local level = info.level or currentLevel flickerstreak@30: info.level = nil flickerstreak@30: local button = AcquireButton(self, level) flickerstreak@30: if not next(info) then flickerstreak@30: info.disabled = true flickerstreak@30: end flickerstreak@30: button.disabled = info.isTitle or info.notClickable or info.disabled or (self.combat and info.secure) flickerstreak@30: button.isTitle = info.isTitle flickerstreak@30: button.notClickable = info.notClickable flickerstreak@30: if button.isTitle then flickerstreak@30: button.text:SetFontObject(GameFontNormalSmall) flickerstreak@30: elseif button.notClickable then flickerstreak@30: button.text:SetFontObject(GameFontHighlightSmall) flickerstreak@30: elseif button.disabled then flickerstreak@30: button.text:SetFontObject(GameFontDisableSmall) flickerstreak@30: else flickerstreak@30: button.text:SetFontObject(GameFontHighlightSmall) flickerstreak@30: end flickerstreak@30: if info.disabled then flickerstreak@30: button.arrow:SetDesaturated(true) flickerstreak@30: button.check:SetDesaturated(true) flickerstreak@30: else flickerstreak@30: button.arrow:SetDesaturated(false) flickerstreak@30: button.check:SetDesaturated(false) flickerstreak@30: end flickerstreak@30: if info.textR and info.textG and info.textB then flickerstreak@30: button.textR = info.textR flickerstreak@30: button.textG = info.textG flickerstreak@30: button.textB = info.textB flickerstreak@30: button.text:SetTextColor(button.textR, button.textG, button.textB) flickerstreak@30: else flickerstreak@30: button.text:SetTextColor(button.text:GetFontObject():GetTextColor()) flickerstreak@30: end flickerstreak@30: button.notCheckable = info.notCheckable flickerstreak@30: button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0) flickerstreak@30: button.checked = not info.notCheckable and info.checked flickerstreak@30: button.mouseoverUnderline = info.mouseoverUnderline flickerstreak@30: button.isRadio = not info.notCheckable and info.isRadio flickerstreak@30: if info.isRadio then flickerstreak@30: button.check:Show() flickerstreak@30: button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") flickerstreak@30: if button.checked then flickerstreak@30: button.check:SetTexCoord(0.25, 0.5, 0, 1) flickerstreak@30: button.check:SetVertexColor(1, 1, 1, 1) flickerstreak@30: else flickerstreak@30: button.check:SetTexCoord(0, 0.25, 0, 1) flickerstreak@30: button.check:SetVertexColor(1, 1, 1, 0.5) flickerstreak@30: end flickerstreak@30: button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") flickerstreak@30: button.check:SetWidth(16) flickerstreak@30: button.check:SetHeight(16) flickerstreak@30: elseif info.icon then flickerstreak@30: button.check:Show() flickerstreak@30: button.check:SetTexture(info.icon) flickerstreak@30: if info.iconWidth and info.iconHeight then flickerstreak@30: button.check:SetWidth(info.iconWidth) flickerstreak@30: button.check:SetHeight(info.iconHeight) flickerstreak@30: else flickerstreak@30: button.check:SetWidth(16) flickerstreak@30: button.check:SetHeight(16) flickerstreak@30: end flickerstreak@30: if info.iconCoordLeft and info.iconCoordRight and info.iconCoordTop and info.iconCoordBottom then flickerstreak@30: button.check:SetTexCoord(info.iconCoordLeft, info.iconCoordRight, info.iconCoordTop, info.iconCoordBottom) flickerstreak@30: elseif info.icon:find("^Interface\\Icons\\") then flickerstreak@30: button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) flickerstreak@30: else flickerstreak@30: button.check:SetTexCoord(0, 1, 0, 1) flickerstreak@30: end flickerstreak@30: button.check:SetVertexColor(1, 1, 1, 1) flickerstreak@30: else flickerstreak@30: if button.checked then flickerstreak@30: if info.checkIcon then flickerstreak@30: button.check:SetWidth(16) flickerstreak@30: button.check:SetHeight(16) flickerstreak@30: button.check:SetTexture(info.checkIcon) flickerstreak@30: if info.checkIcon:find("^Interface\\Icons\\") then flickerstreak@30: button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) flickerstreak@30: else flickerstreak@30: button.check:SetTexCoord(0, 1, 0, 1) flickerstreak@30: end flickerstreak@30: else flickerstreak@30: button.check:SetWidth(24) flickerstreak@30: button.check:SetHeight(24) flickerstreak@30: button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") flickerstreak@30: button.check:SetTexCoord(0, 1, 0, 1) flickerstreak@30: end flickerstreak@30: button.check:SetVertexColor(1, 1, 1, 1) flickerstreak@30: else flickerstreak@30: button.check:SetVertexColor(1, 1, 1, 0) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: if not button.disabled then flickerstreak@30: button.func = info.func flickerstreak@30: button.secure = info.secure flickerstreak@30: end flickerstreak@30: button.hasColorSwatch = info.hasColorSwatch flickerstreak@30: if button.hasColorSwatch then flickerstreak@30: button.colorSwatch:Show() flickerstreak@30: button.colorSwatch.texture:Show() flickerstreak@30: button.r = info.r or 1 flickerstreak@30: button.g = info.g or 1 flickerstreak@30: button.b = info.b or 1 flickerstreak@30: button.colorSwatch.texture:SetVertexColor(button.r, button.g, button.b) flickerstreak@30: button.checked = false flickerstreak@30: button.func = nil flickerstreak@30: button.colorFunc = info.colorFunc flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "colorArg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: button.hasOpacity = info.hasOpacity flickerstreak@30: button.opacity = info.opacity or 1 flickerstreak@30: else flickerstreak@30: button.colorSwatch:Hide() flickerstreak@30: button.colorSwatch.texture:Hide() flickerstreak@30: end flickerstreak@30: button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow flickerstreak@30: if button.hasArrow then flickerstreak@30: button.arrow:SetAlpha(1) flickerstreak@30: if info.hasSlider then flickerstreak@30: button.hasSlider = true flickerstreak@30: button.sliderMin = info.sliderMin or 0 flickerstreak@30: button.sliderMax = info.sliderMax or 1 flickerstreak@30: button.sliderStep = info.sliderStep or 0 flickerstreak@30: button.sliderBigStep = info.sliderBigStep or button.sliderStep flickerstreak@30: if button.sliderBigStep < button.sliderStep then flickerstreak@30: button.sliderBigStep = button.sliderStep flickerstreak@30: end flickerstreak@30: button.sliderIsPercent = info.sliderIsPercent and true or false flickerstreak@30: button.sliderMinText = info.sliderMinText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMin * 100) or button.sliderMin flickerstreak@30: button.sliderMaxText = info.sliderMaxText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMax * 100) or button.sliderMax flickerstreak@30: button.sliderFunc = info.sliderFunc flickerstreak@30: button.sliderValue = info.sliderValue flickerstreak@30: button.fromAceOptions = info.fromAceOptions flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "sliderArg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: elseif info.hasEditBox then flickerstreak@30: button.hasEditBox = true flickerstreak@30: button.editBoxText = info.editBoxText or "" flickerstreak@30: button.editBoxFunc = info.editBoxFunc flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "editBoxArg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: button.editBoxChangeFunc = info.editBoxChangeFunc flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "editBoxChangeArg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: button.editBoxValidateFunc = info.editBoxValidateFunc flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "editBoxValidateArg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: button.editBoxIsKeybinding = info.editBoxIsKeybinding flickerstreak@30: button.editBoxKeybindingOnly = info.editBoxKeybindingOnly flickerstreak@30: button.editBoxKeybindingExcept = info.editBoxKeybindingExcept flickerstreak@30: else flickerstreak@30: button.value = info.value flickerstreak@30: local l = levels[level+1] flickerstreak@30: if l and info.value == l.value then flickerstreak@30: -- button.arrow:SetWidth(24) flickerstreak@30: -- button.arrow:SetHeight(24) flickerstreak@30: button.selected = true flickerstreak@30: button.highlight:Show() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: else flickerstreak@30: button.arrow:SetAlpha(0) flickerstreak@30: end flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "arg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: button.closeWhenClicked = info.closeWhenClicked flickerstreak@30: button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10 flickerstreak@30: local font,_ = button.text:GetFont() flickerstreak@30: button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) flickerstreak@30: button:SetHeight(button.textHeight + 6) flickerstreak@30: button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT") flickerstreak@30: button.text:SetJustifyH(info.justifyH or "LEFT") flickerstreak@30: button.text:SetText(info.text) flickerstreak@30: button.tooltipTitle = info.tooltipTitle flickerstreak@30: button.tooltipText = info.tooltipText flickerstreak@30: button.tooltipFunc = info.tooltipFunc flickerstreak@30: local i = 1 flickerstreak@30: while true do flickerstreak@30: local k = "tooltipArg" .. i flickerstreak@30: local x = info[k] flickerstreak@30: if x == nil then flickerstreak@30: break flickerstreak@30: end flickerstreak@30: button[k] = x flickerstreak@30: i = i + 1 flickerstreak@30: end flickerstreak@30: if not button.tooltipTitle and not button.tooltipText and not button.tooltipFunc and not info.isTitle then flickerstreak@30: button.tooltipTitle = info.text flickerstreak@30: end flickerstreak@30: if type(button.func) == "string" then flickerstreak@30: if type(button.arg1) ~= "table" then flickerstreak@30: self:error("Cannot call method %q on a non-table", button.func) flickerstreak@30: end flickerstreak@30: if type(button.arg1[button.func]) ~= "function" then flickerstreak@30: self:error("Method %q nonexistant.", button.func) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:InjectAceOptionsTable(handler, options) flickerstreak@30: self:argCheck(handler, 2, "table") flickerstreak@30: self:argCheck(options, 3, "table") flickerstreak@30: if tostring(options.type):lower() ~= "group" then flickerstreak@30: self:error('Cannot inject into options table argument #3 if its type is not "group"') flickerstreak@30: end flickerstreak@30: if options.handler ~= nil and options.handler ~= handler then flickerstreak@30: self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") flickerstreak@30: end flickerstreak@30: options.handler = handler flickerstreak@30: local class = handler.class flickerstreak@30: if not AceLibrary:HasInstance("AceOO-2.0") or not class then flickerstreak@30: if Rock then flickerstreak@30: -- possible Rock object flickerstreak@30: for mixin in Rock:IterateObjectMixins(handler) do flickerstreak@30: if type(mixin.GetAceOptionsDataTable) == "function" then flickerstreak@30: local t = mixin:GetAceOptionsDataTable(handler) flickerstreak@30: for k,v in pairs(t) do flickerstreak@30: if type(options.args) ~= "table" then flickerstreak@30: options.args = {} flickerstreak@30: end flickerstreak@30: if options.args[k] == nil then flickerstreak@30: options.args[k] = v flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: else flickerstreak@30: -- Ace2 object flickerstreak@30: while class and class ~= AceLibrary("AceOO-2.0").Class do flickerstreak@30: if type(class.GetAceOptionsDataTable) == "function" then flickerstreak@30: local t = class:GetAceOptionsDataTable(handler) flickerstreak@30: for k,v in pairs(t) do flickerstreak@30: if type(options.args) ~= "table" then flickerstreak@30: options.args = {} flickerstreak@30: end flickerstreak@30: if options.args[k] == nil then flickerstreak@30: options.args[k] = v flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: local mixins = class.mixins flickerstreak@30: if mixins then flickerstreak@30: for mixin in pairs(mixins) do flickerstreak@30: if type(mixin.GetAceOptionsDataTable) == "function" then flickerstreak@30: local t = mixin:GetAceOptionsDataTable(handler) flickerstreak@30: for k,v in pairs(t) do flickerstreak@30: if type(options.args) ~= "table" then flickerstreak@30: options.args = {} flickerstreak@30: end flickerstreak@30: if options.args[k] == nil then flickerstreak@30: options.args[k] = v flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end flickerstreak@30: class = class.super flickerstreak@30: end flickerstreak@30: end flickerstreak@30: return options flickerstreak@30: end flickerstreak@30: flickerstreak@30: function Dewdrop:OnTooltipHide() flickerstreak@30: if lastSetFont then flickerstreak@30: if lastSetFont == normalFont then flickerstreak@30: lastSetFont = nil flickerstreak@30: return flickerstreak@30: end flickerstreak@30: fillRegionTmp(GameTooltip:GetRegions()) flickerstreak@30: for i,v in ipairs(regionTmp) do flickerstreak@30: if v.GetFont then flickerstreak@30: local font,size,outline = v:GetFont() flickerstreak@30: if font == lastSetFont then flickerstreak@30: v:SetFont(normalFont, size, outline) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: regionTmp[i] = nil flickerstreak@30: end flickerstreak@30: lastSetFont = nil flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function activate(self, oldLib, oldDeactivate) flickerstreak@30: Dewdrop = self flickerstreak@30: if oldLib and oldLib.registry then flickerstreak@30: self.registry = oldLib.registry flickerstreak@30: self.onceRegistered = oldLib.onceRegistered flickerstreak@30: else flickerstreak@30: self.registry = {} flickerstreak@30: self.onceRegistered = {} flickerstreak@30: flickerstreak@30: local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") flickerstreak@30: local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") flickerstreak@30: local oldX, oldY, clickTime flickerstreak@30: WorldFrame:SetScript("OnMouseDown", function(this, ...) flickerstreak@30: oldX,oldY = GetCursorPosition() flickerstreak@30: clickTime = GetTime() flickerstreak@30: if WorldFrame_OnMouseDown then flickerstreak@30: WorldFrame_OnMouseDown(this, ...) flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: flickerstreak@30: WorldFrame:SetScript("OnMouseUp", function(this, ...) flickerstreak@30: local x,y = GetCursorPosition() flickerstreak@30: if not oldX or not oldY or not x or not y or not clickTime then flickerstreak@30: self:Close() flickerstreak@30: if WorldFrame_OnMouseUp then flickerstreak@30: WorldFrame_OnMouseUp(this, ...) flickerstreak@30: end flickerstreak@30: return flickerstreak@30: end flickerstreak@30: local d = math.abs(x - oldX) + math.abs(y - oldY) flickerstreak@30: if d <= 5 and GetTime() - clickTime < 0.5 then flickerstreak@30: self:Close() flickerstreak@30: end flickerstreak@30: if WorldFrame_OnMouseUp then flickerstreak@30: WorldFrame_OnMouseUp(this, ...) flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: flickerstreak@30: hooksecurefunc(DropDownList1, "Show", function() flickerstreak@30: if levels[1] and levels[1]:IsVisible() then flickerstreak@30: self:Close() flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: flickerstreak@30: hooksecurefunc("HideDropDownMenu", function() flickerstreak@30: if levels[1] and levels[1]:IsVisible() then flickerstreak@30: self:Close() flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: flickerstreak@30: hooksecurefunc("CloseDropDownMenus", function() flickerstreak@30: if levels[1] and levels[1]:IsVisible() then flickerstreak@30: local stack = debugstack() flickerstreak@30: if not stack:find("`TargetFrame_OnHide'") then flickerstreak@30: self:Close() flickerstreak@30: end flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: end flickerstreak@30: self.frame = oldLib and oldLib.frame or CreateFrame("Frame") flickerstreak@30: self.frame:UnregisterAllEvents() flickerstreak@30: self.frame:RegisterEvent("PLAYER_REGEN_ENABLED") flickerstreak@30: self.frame:RegisterEvent("PLAYER_REGEN_DISABLED") flickerstreak@30: self.frame:Hide() flickerstreak@30: self.frame:SetScript("OnEvent", function(this, event) flickerstreak@30: this:Show() flickerstreak@30: if event=="PLAYER_REGEN_ENABLED" then -- track combat state for secure frame operations flickerstreak@30: self.combat = false flickerstreak@30: elseif event=="PLAYER_REGEN_DISABLED" then flickerstreak@30: self.combat = true flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: self.frame:SetScript("OnUpdate", function(this) flickerstreak@30: this:Hide() flickerstreak@30: self:Refresh(1) flickerstreak@30: end) flickerstreak@30: self.hookedTooltip = true flickerstreak@30: if not oldLib or not oldLib.hookedTooltip then flickerstreak@30: local OnTooltipHide = GameTooltip:GetScript("OnHide") flickerstreak@30: GameTooltip:SetScript("OnHide", function(this, ...) flickerstreak@30: if OnTooltipHide then flickerstreak@30: OnTooltipHide(this, ...) flickerstreak@30: end flickerstreak@30: if type(self.OnTooltipHide) == "function" then flickerstreak@30: self:OnTooltipHide() flickerstreak@30: end flickerstreak@30: end) flickerstreak@30: end flickerstreak@30: levels = {} flickerstreak@30: buttons = {} flickerstreak@30: flickerstreak@30: if oldDeactivate then flickerstreak@30: oldDeactivate(oldLib) flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: local function external(lib, major, instance) flickerstreak@30: if major == "SharedMedia-1.0" then flickerstreak@30: SharedMedia = instance flickerstreak@30: end flickerstreak@30: end flickerstreak@30: flickerstreak@30: AceLibrary:Register(Dewdrop, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)