-- $Id: LibUIDropDownMenu.lua 123 2023-07-29 01:42:12Z arithmandar $ -- ---------------------------------------------------------------------------- -- Localized Lua globals. -- ---------------------------------------------------------------------------- local _G = getfenv(0) local tonumber, type, string, table = _G.tonumber, _G.type, _G.string, _G.table local tinsert = table.insert local strsub, strlen, strmatch, gsub = _G.strsub, _G.strlen, _G.strmatch, _G.gsub local max, match = _G.max, _G.match local securecall, issecure = _G.securecall, _G.issecure local wipe = table.wipe -- WoW local CreateFrame, GetCursorPosition, GetCVar, GetScreenHeight, GetScreenWidth, PlaySound = _G.CreateFrame, _G.GetCursorPosition, _G.GetCVar, _G.GetScreenHeight, _G.GetScreenWidth, _G.PlaySound local GetBuildInfo = _G.GetBuildInfo local GameTooltip, GetAppropriateTooltip, tooltip, GetValueOrCallFunction local CloseMenus, ShowUIPanel = _G.CloseMenus, _G.ShowUIPanel local GameTooltip_SetTitle, GameTooltip_AddInstructionLine, GameTooltip_AddNormalLine, GameTooltip_AddColoredLine = _G.GameTooltip_SetTitle, _G.GameTooltip_AddInstructionLine, _G.GameTooltip_AddNormalLine, _G.GameTooltip_AddColoredLine -- ---------------------------------------------------------------------------- local MAJOR_VERSION = "LibUIDropDownMenu-4.0" local MINOR_VERSION = 90000 + tonumber(("$Rev: 123 $"):match("%d+")) local LibStub = _G.LibStub if not LibStub then error(MAJOR_VERSION .. " requires LibStub.") end local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION) if not lib then return end -- Determine WoW TOC Version local WoWClassicEra, WoWClassicTBC, WoWWOTLKC, WoWRetail local wowversion = select(4, GetBuildInfo()) if wowversion < 20000 then WoWClassicEra = true elseif wowversion < 30000 then WoWClassicTBC = true elseif wowversion < 40000 then WoWWOTLKC = true elseif wowversion > 90000 then WoWRetail = true else -- n/a end if WoWClassicEra or WoWClassicTBC or WoWWOTLKC then GameTooltip = _G.GameTooltip tooltip = GameTooltip else -- Retail GetAppropriateTooltip = _G.GetAppropriateTooltip tooltip = GetAppropriateTooltip() GetValueOrCallFunction = _G.GetValueOrCallFunction end -- ////////////////////////////////////////////////////////////// L_UIDROPDOWNMENU_MINBUTTONS = 8; -- classic only L_UIDROPDOWNMENU_MAXBUTTONS = 1; L_UIDROPDOWNMENU_MAXLEVELS = 3; L_UIDROPDOWNMENU_BUTTON_HEIGHT = 16; L_UIDROPDOWNMENU_BORDER_HEIGHT = 15; -- The current open menu L_UIDROPDOWNMENU_OPEN_MENU = nil; -- The current menu being initialized L_UIDROPDOWNMENU_INIT_MENU = nil; -- Current level shown of the open menu L_UIDROPDOWNMENU_MENU_LEVEL = 1; -- Current value of the open menu L_UIDROPDOWNMENU_MENU_VALUE = nil; -- Time to wait to hide the menu L_UIDROPDOWNMENU_SHOW_TIME = 2; -- Default dropdown text height L_UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = nil; -- For Classic checkmarks, this is the additional padding that we give to the button text. L_UIDROPDOWNMENU_CLASSIC_CHECK_PADDING = 4; -- Default dropdown width padding L_UIDROPDOWNMENU_DEFAULT_WIDTH_PADDING = 25; -- List of open menus L_OPEN_DROPDOWNMENUS = {}; local L_DropDownList1, L_DropDownList2, L_DropDownList3 local delegateFrame = CreateFrame("FRAME"); delegateFrame:SetScript("OnAttributeChanged", function(self, attribute, value) if ( attribute == "createframes" and value == true ) then lib:UIDropDownMenu_CreateFrames(self:GetAttribute("createframes-level"), self:GetAttribute("createframes-index")); elseif ( attribute == "initmenu" ) then L_UIDROPDOWNMENU_INIT_MENU = value; elseif ( attribute == "openmenu" ) then L_UIDROPDOWNMENU_OPEN_MENU = value; end end); function lib:UIDropDownMenu_InitializeHelper(frame) -- This deals with the potentially tainted stuff! if ( frame ~= L_UIDROPDOWNMENU_OPEN_MENU ) then L_UIDROPDOWNMENU_MENU_LEVEL = 1; end -- Set the frame that's being intialized delegateFrame:SetAttribute("initmenu", frame); -- Hide all the buttons local button, dropDownList; for i = 1, L_UIDROPDOWNMENU_MAXLEVELS, 1 do dropDownList = _G["L_DropDownList"..i]; if ( i >= L_UIDROPDOWNMENU_MENU_LEVEL or frame ~= L_UIDROPDOWNMENU_OPEN_MENU ) then dropDownList.numButtons = 0; dropDownList.maxWidth = 0; for j=1, L_UIDROPDOWNMENU_MAXBUTTONS, 1 do button = _G["L_DropDownList"..i.."Button"..j]; button:Hide(); end dropDownList:Hide(); end end frame:SetHeight(L_UIDROPDOWNMENU_BUTTON_HEIGHT * 2); end function lib:UIDropDownMenuButton_ShouldShowIconTooltip(self) if self.Icon and (self.iconTooltipTitle or self.iconTooltipText) and (self.icon or self.mouseOverIcon) then return GetMouseFocus() == self.Icon; end return false; end -- ////////////////////////////////////////////////////////////// -- L_UIDropDownMenuButtonTemplate local function create_MenuButton(name, parent) -- UIDropDownMenuButton Scripts BEGIN local function button_OnEnter(self) if ( self.hasArrow ) then local level = self:GetParent():GetID() + 1; local listFrame = _G["L_DropDownList"..level]; if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint(1)) ~= self ) then lib:ToggleDropDownMenu(self:GetParent():GetID() + 1, self.value, nil, nil, nil, nil, self.menuList, self, nil, self.menuListDisplayMode); end else lib:CloseDropDownMenus(self:GetParent():GetID() + 1); end self.Highlight:Show(); if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then lib:UIDropDownMenu_StopCounting(self:GetParent()); end -- To check: do we need special handle for classic since there is no UIDropDownMenuButton_ShouldShowIconTooltip()? -- if ( self.tooltipTitle and not self.noTooltipWhileEnabled ) then if ( self.tooltipTitle and not self.noTooltipWhileEnabled and not lib:UIDropDownMenuButton_ShouldShowIconTooltip(self)) then if ( self.tooltipOnButton ) then tooltip:SetOwner(self, "ANCHOR_RIGHT"); GameTooltip_SetTitle(tooltip, self.tooltipTitle); if self.tooltipInstruction then GameTooltip_AddInstructionLine(tooltip, self.tooltipInstruction); end if self.tooltipText then GameTooltip_AddNormalLine(tooltip, self.tooltipText, true); end if self.tooltipWarning then GameTooltip_AddColoredLine(tooltip, self.tooltipWarning, RED_FONT_COLOR, true); end if self.tooltipBackdropStyle then SharedTooltip_SetBackdropStyle(tooltip, self.tooltipBackdropStyle); end tooltip:Show(); end end if ( self.mouseOverIcon ~= nil ) then self.Icon:SetTexture(self.mouseOverIcon); self.Icon:Show(); end if (WoWRetail) then GetValueOrCallFunction(self, "funcOnEnter", self); end end local function button_OnLeave(self) self.Highlight:Hide(); if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then lib:UIDropDownMenu_StartCounting(self:GetParent()); end tooltip:Hide(); if ( self.mouseOverIcon ~= nil ) then if ( self.icon ~= nil ) then self.Icon:SetTexture(self.icon); else self.Icon:Hide(); end end if (WoWRetail) then GetValueOrCallFunction(self, "funcOnLeave", self); end end local function button_OnClick(self, button) local checked = self.checked; if ( type (checked) == "function" ) then checked = checked(self); end if ( self.keepShownOnClick ) then if not self.notCheckable then if ( checked ) then _G[self:GetName().."Check"]:Hide(); _G[self:GetName().."UnCheck"]:Show(); checked = false; else _G[self:GetName().."Check"]:Show(); _G[self:GetName().."UnCheck"]:Hide(); checked = true; end end else self:GetParent():Hide(); end if ( type (self.checked) ~= "function" ) then self.checked = checked; end -- saving this here because func might use a dropdown, changing this self's attributes local playSound = true; if ( self.noClickSound ) then playSound = false; end local func = self.func; if ( func ) then func(self, self.arg1, self.arg2, checked, button); else return; end if ( playSound ) then PlaySound(SOUNDKIT.U_CHAT_SCROLL_BUTTON); end end -- UIDropDownMenuButton Scripts END -- UIDropDownMenuButtonIcon Script BEGIN local function icon_OnClick(self, button) local button = self:GetParent() if not button then return end button_OnClick(self, button) end local function icon_OnEnter(self) local button = self:GetParent(); if not button then return; end local shouldShowIconTooltip = lib:UIDropDownMenuButton_ShouldShowIconTooltip(button); if shouldShowIconTooltip then tooltip:SetOwner(button, "ANCHOR_RIGHT"); if button.iconTooltipTitle then GameTooltip_SetTitle(tooltip, button.iconTooltipTitle); end if button.iconTooltipText then GameTooltip_AddNormalLine(tooltip, button.iconTooltipText, true); end if button.iconTooltipBackdropStyle then SharedTooltip_SetBackdropStyle(tooltip, button.iconTooltipBackdropStyle); end tooltip:Show(); end button_OnEnter(button); end local function icon_OnLeave(self) local button = self:GetParent(); if not button then return; end button_OnLeave(button); end local function icon_OnMouseUp(self, button) if ( button == "LeftButton" ) then icon_OnClick(self, button) end end -- UIDropDownMenuButtonIcon Script END local f = CreateFrame("Button", name, parent or nil) f:SetWidth(100) f:SetHeight(16) f:SetFrameLevel(f:GetParent():GetFrameLevel()+2) f.Highlight = f:CreateTexture(name.."Highlight", "BACKGROUND") f.Highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") f.Highlight:SetBlendMode("ADD") f.Highlight:SetAllPoints() f.Highlight:Hide() f.Check = f:CreateTexture(name.."Check", "ARTWORK") f.Check:SetTexture("Interface\\Common\\UI-DropDownRadioChecks") f.Check:SetSize(16, 16) f.Check:SetPoint("LEFT", f, 0, 0) f.Check:SetTexCoord(0, 0.5, 0.5, 1) f.UnCheck = f:CreateTexture(name.."UnCheck", "ARTWORK") f.UnCheck:SetTexture("Interface\\Common\\UI-DropDownRadioChecks") f.UnCheck:SetSize(16, 16) f.UnCheck:SetPoint("LEFT", f, 0, 0) f.UnCheck:SetTexCoord(0.5, 1, 0.5, 1) local fIcon fIcon = f:CreateTexture(name.."Icon", "ARTWORK") fIcon:SetSize(16, 16) fIcon:SetPoint("RIGHT", f, 0, 0) fIcon:Hide() if (WoWRetail) then fIcon:SetScript("OnEnter", function(self) icon_OnEnter(self) end) fIcon:SetScript("OnLeave", function(self) icon_OnLeave(self) end) fIcon:SetScript("OnMouseUp", function(self, button) icon_OnMouseUp(self, button) end) end f.Icon = fIcon -- ColorSwatch local fcw fcw = CreateFrame("Button", name.."ColorSwatch", f, BackdropTemplateMixin and DropDownMenuButtonMixin and "BackdropTemplate,ColorSwatchTemplate" or BackdropTemplateMixin and "BackdropTemplate" or nil) fcw:SetPoint("RIGHT", f, -6, 0) fcw:Hide() if not DropDownMenuButtonMixin then fcw:SetSize(16, 16) fcw.SwatchBg = fcw:CreateTexture(name.."ColorSwatchSwatchBg", "BACKGROUND") fcw.SwatchBg:SetVertexColor(1, 1, 1) fcw.SwatchBg:SetWidth(14) fcw.SwatchBg:SetHeight(14) fcw.SwatchBg:SetPoint("CENTER", fcw, 0, 0) local button1NormalTexture = fcw:CreateTexture(name.."ColorSwatchNormalTexture") button1NormalTexture:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") button1NormalTexture:SetAllPoints() fcw:SetNormalTexture(button1NormalTexture) end fcw:SetScript("OnClick", function(self, button, down) CloseMenus() lib:UIDropDownMenuButton_OpenColorPicker(self:GetParent()) end) fcw:SetScript("OnEnter", function(self, motion) lib:CloseDropDownMenus(self:GetParent():GetParent():GetID() + 1) _G[self:GetName().."SwatchBg"]:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b) lib:UIDropDownMenu_StopCounting(self:GetParent():GetParent()) end) fcw:SetScript("OnLeave", function(self, motion) _G[self:GetName().."SwatchBg"]:SetVertexColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b); lib:UIDropDownMenu_StartCounting(self:GetParent():GetParent()) end) f.ColorSwatch = fcw -- ExpandArrow local fea = CreateFrame("Button", name.."ExpandArrow", f) fea:SetSize(16, 16) fea:SetPoint("RIGHT", f, 0, 0) fea:Hide() local button2NormalTexture = fea:CreateTexture(name.."ExpandArrowNormalTexture") button2NormalTexture:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") button2NormalTexture:SetAllPoints() fea:SetNormalTexture(button2NormalTexture) fea:SetScript("OnMouseDown", function(self, button) if self:IsEnabled() then lib:ToggleDropDownMenu(self:GetParent():GetParent():GetID() + 1, self:GetParent().value, nil, nil, nil, nil, self:GetParent().menuList, self); PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); end end) fea:SetScript("OnEnter", function(self, motion) local level = self:GetParent():GetParent():GetID() + 1 lib:CloseDropDownMenus(level) if self:IsEnabled() then local listFrame = _G["L_DropDownList"..level]; if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint()) ~= self ) then lib:ToggleDropDownMenu(level, self:GetParent().value, nil, nil, nil, nil, self:GetParent().menuList, self) end end lib:UIDropDownMenu_StopCounting(self:GetParent():GetParent()) end) fea:SetScript("OnLeave", function(self, motion) lib:UIDropDownMenu_StartCounting(self:GetParent():GetParent()) end) f.ExpandArrow = fea -- InvisibleButton local fib = CreateFrame("Button", name.."InvisibleButton", f) fib:Hide() fib:SetPoint("TOPLEFT", f, 0, 0) fib:SetPoint("BOTTOMLEFT", f, 0, 0) fib:SetPoint("RIGHT", fcw, "LEFT", 0, 0) fib:SetScript("OnEnter", function(self, motion) if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then lib:UIDropDownMenu_StopCounting(self:GetParent():GetParent()); end lib:CloseDropDownMenus(self:GetParent():GetParent():GetID() + 1); local parent = self:GetParent(); if ( parent.tooltipTitle and parent.tooltipWhileDisabled) then if ( parent.tooltipOnButton ) then tooltip:SetOwner(parent, "ANCHOR_RIGHT"); GameTooltip_SetTitle(tooltip, parent.tooltipTitle); if parent.tooltipInstruction then GameTooltip_AddInstructionLine(tooltip, parent.tooltipInstruction); end if parent.tooltipText then GameTooltip_AddNormalLine(tooltip, parent.tooltipText, true); end if parent.tooltipWarning then GameTooltip_AddColoredLine(tooltip, parent.tooltipWarning, RED_FONT_COLOR, true); end if parent.tooltipBackdropStyle then SharedTooltip_SetBackdropStyle(tooltip, parent.tooltipBackdropStyle); end tooltip:Show(); end end end) fib:SetScript("OnLeave", function(self, motion) if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then lib:UIDropDownMenu_StartCounting(self:GetParent():GetParent()); end tooltip:Hide(); end) f.invisibleButton = fib f:SetScript("OnClick", function(self, button) button_OnClick(self, button) end) f:SetScript("OnEnter", function(self, motion) button_OnEnter(self) end) f:SetScript("OnLeave", function(self, motion) button_OnLeave(self) end) f:SetScript("OnEnable", function(self) self.invisibleButton:Hide() end) f:SetScript("OnDisable", function(self) self.invisibleButton:Show() end) local text1 = f:CreateFontString(name.."NormalText") f:SetFontString(text1) text1:SetPoint("LEFT", f, -5, 0) f:SetNormalFontObject("GameFontHighlightSmallLeft") f:SetHighlightFontObject("GameFontHighlightSmallLeft") f:SetDisabledFontObject("GameFontDisableSmallLeft") return f end -- ////////////////////////////////////////////////////////////// -- L_UIDropDownListTemplate local function creatre_DropDownList(name, parent) -- This has been removed from Backdrop.lua, so we added the definition here. local BACKDROP_DIALOG_DARK = { bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark", edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileEdge = true, tileSize = 32, edgeSize = 32, insets = { left = 11, right = 12, top = 12, bottom = 11, }, } local BACKDROP_TOOLTIP_16_16_5555 = { bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileEdge = true, tileSize = 16, edgeSize = 16, insets = { left = 5, right = 5, top = 5, bottom = 5 }, } local f = _G[name] or CreateFrame("Button", name) f:SetParent(parent or nil) f:Hide() f:SetFrameStrata("DIALOG") f:EnableMouse(true) local fbd = _G[name.."Backdrop"] or CreateFrame("Frame", name.."Backdrop", f, BackdropTemplateMixin and "DialogBorderDarkTemplate" or nil) fbd:SetAllPoints() fbd.backdropInfo = BACKDROP_DIALOG_DARK f.Backdrop = fbd local fmb = _G[name.."MenuBackdrop"] or CreateFrame("Frame", name.."MenuBackdrop", f, TooltipBackdropTemplateMixin and "TooltipBackdropTemplate" or nil) fmb:SetAllPoints() fmb.backdropInfo = BACKDROP_TOOLTIP_16_16_5555 fmb:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) fmb:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) f.MenuBackdrop = fmb f.Button1 = _G[name.."Button1"] or create_MenuButton(name.."Button1", f) -- to replace the inherits of "UIDropDownMenuButtonTemplate" f.Button1:SetID(1) f:SetScript("OnClick", function(self) self:Hide() end) f:SetScript("OnEnter", function(self, motion) if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then lib:UIDropDownMenu_StopCounting(self, motion) end end) f:SetScript("OnLeave", function(self, motion) if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then lib:UIDropDownMenu_StartCounting(self, motion) end end) -- If dropdown is visible then see if its timer has expired, if so hide the frame f:SetScript("OnUpdate", function(self, elapsed) if ( self.shouldRefresh ) then lib:UIDropDownMenu_RefreshDropDownSize(self); self.shouldRefresh = false; end if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then if ( not self.showTimer or not self.isCounting ) then return; elseif ( self.showTimer < 0 ) then self:Hide(); self.showTimer = nil; self.isCounting = nil; else self.showTimer = self.showTimer - elapsed; end end end) f:SetScript("OnShow", function(self) if ( self.onShow ) then self.onShow(); self.onShow = nil; end for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do if (not self.noResize) then _G[self:GetName().."Button"..i]:SetWidth(self.maxWidth); end end if (not self.noResize) then self:SetWidth(self.maxWidth+25); end if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then self.showTimer = nil; end if ( self:GetID() > 1 ) then self.parent = _G["L_DropDownList"..(self:GetID() - 1)]; end EventRegistry:TriggerEvent("UIDropDownMenu.Show", self); end) f:SetScript("OnHide", function(self) local id = self:GetID() if ( self.onHide ) then self.onHide(id+1); self.onHide = nil; end if ( self.baseFrameStrata ) then self:SetFrameStrata(self.baseFrameStrata); self.baseFrameStrata = nil; end lib:CloseDropDownMenus(id+1); L_OPEN_DROPDOWNMENUS[id] = nil; if (id == 1) then L_UIDROPDOWNMENU_OPEN_MENU = nil; end lib:UIDropDownMenu_ClearCustomFrames(self); EventRegistry:TriggerEvent("UIDropDownMenu.Hide"); end) return f end -- ////////////////////////////////////////////////////////////// -- L_UIDropDownMenuTemplate local function create_DropDownMenu(name, parent) local f if type(name) == "table" then f = name name = f:GetName() else f = CreateFrame("Frame", name, parent or nil) end if not name then name = "" end f:SetSize(40, 32) f.Left = f:CreateTexture(name.."Left", "ARTWORK") f.Left:SetTexture("Interface\\Glues\\CharacterCreate\\CharacterCreate-LabelFrame") f.Left:SetSize(25, 64) f.Left:SetPoint("TOPLEFT", f, 0, 17) f.Left:SetTexCoord(0, 0.1953125, 0, 1) f.Middle = f:CreateTexture(name.."Middle", "ARTWORK") f.Middle:SetTexture("Interface\\Glues\\CharacterCreate\\CharacterCreate-LabelFrame") f.Middle:SetSize(115, 64) f.Middle:SetPoint("LEFT", f.Left, "RIGHT") f.Middle:SetTexCoord(0.1953125, 0.8046875, 0, 1) f.Right = f:CreateTexture(name.."Right", "ARTWORK") f.Right:SetTexture("Interface\\Glues\\CharacterCreate\\CharacterCreate-LabelFrame") f.Right:SetSize(25, 64) f.Right:SetPoint("LEFT", f.Middle, "RIGHT") f.Right:SetTexCoord(0.8046875, 1, 0, 1) f.Text = f:CreateFontString(name.."Text", "ARTWORK", "GameFontHighlightSmall") f.Text:SetWordWrap(false) f.Text:SetJustifyH("RIGHT") f.Text:SetSize(0, 10) f.Text:SetPoint("RIGHT", f.Right, -43, 2) f.Icon = f:CreateTexture(name.."Icon", "OVERLAY") f.Icon:Hide() f.Icon:SetSize(16, 16) f.Icon:SetPoint("LEFT", 30, 2) -- // UIDropDownMenuButtonScriptTemplate f.Button = CreateFrame("Button", name.."Button", f) f.Button:SetMotionScriptsWhileDisabled(true) f.Button:SetSize(24, 24) f.Button:SetPoint("TOPRIGHT", f.Right, -16, -18) f.Button.NormalTexture = f.Button:CreateTexture(name.."NormalTexture") f.Button.NormalTexture:SetTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up") f.Button.NormalTexture:SetSize(24, 24) f.Button.NormalTexture:SetPoint("RIGHT", f.Button, 0, 0) f.Button:SetNormalTexture(f.Button.NormalTexture) f.Button.PushedTexture = f.Button:CreateTexture(name.."PushedTexture") f.Button.PushedTexture:SetTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down") f.Button.PushedTexture:SetSize(24, 24) f.Button.PushedTexture:SetPoint("RIGHT", f.Button, 0, 0) f.Button:SetPushedTexture(f.Button.PushedTexture) f.Button.DisabledTexture = f.Button:CreateTexture(name.."DisabledTexture") f.Button.DisabledTexture:SetTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled") f.Button.DisabledTexture:SetSize(24, 24) f.Button.DisabledTexture:SetPoint("RIGHT", f.Button, 0, 0) f.Button:SetDisabledTexture(f.Button.DisabledTexture) f.Button.HighlightTexture = f.Button:CreateTexture(name.."HighlightTexture") f.Button.HighlightTexture:SetTexture("Interface\\Buttons\\UI-Common-MouseHilight") f.Button.HighlightTexture:SetSize(24, 24) f.Button.HighlightTexture:SetPoint("RIGHT", f.Button, 0, 0) f.Button.HighlightTexture:SetBlendMode("ADD") f.Button:SetHighlightTexture(f.Button.HighlightTexture) -- Button Script f.Button:SetScript("OnEnter", function(self, motion) local parent = self:GetParent() local myscript = parent:GetScript("OnEnter") if(myscript ~= nil) then myscript(parent) end end) f.Button:SetScript("OnLeave", function(self, motion) local parent = self:GetParent() local myscript = parent:GetScript("OnLeave") if(myscript ~= nil) then myscript(parent) end end) f.Button:SetScript("OnMouseDown", function(self, button) if self:IsEnabled() then local parent = self:GetParent() lib:ToggleDropDownMenu(nil, nil, parent) PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON) end end) -- UIDropDownMenu Script f:SetScript("OnHide", function(self) lib:CloseDropDownMenus() end) return f end -- End of frame templates -- ////////////////////////////////////////////////////////////// -- ////////////////////////////////////////////////////////////// -- Handling two frames from LibUIDropDownMenu.xml local function create_DropDownButtons() L_DropDownList1 = creatre_DropDownList("L_DropDownList1") L_DropDownList1:SetToplevel(true) L_DropDownList1:SetFrameStrata("FULLSCREEN_DIALOG") L_DropDownList1:Hide() L_DropDownList1:SetID(1) L_DropDownList1:SetSize(180, 10) local _, fontHeight, _ = _G["L_DropDownList1Button1NormalText"]:GetFont() L_UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = fontHeight L_DropDownList2 = creatre_DropDownList("L_DropDownList2") L_DropDownList2:SetToplevel(true) L_DropDownList2:SetFrameStrata("FULLSCREEN_DIALOG") L_DropDownList2:Hide() L_DropDownList2:SetID(2) L_DropDownList2:SetSize(180, 10) L_DropDownList3 = creatre_DropDownList("L_DropDownList3") L_DropDownList3:SetToplevel(true) L_DropDownList3:SetFrameStrata("FULLSCREEN_DIALOG") L_DropDownList3:Hide() L_DropDownList3:SetID(3) L_DropDownList3:SetSize(180, 10) -- UIParent integration; since we customize the name of DropDownList, we need to add it to golbal UIMenus table. --tinsert(UIMenus, "L_DropDownList1"); --tinsert(UIMenus, "L_DropDownList2"); --tinsert(UIMenus, "L_DropDownList3"); -- Alternative by Dahk Celes (DDC) that avoids tainting UIMenus and CloseMenus() hooksecurefunc("CloseMenus", function() L_DropDownList1:Hide() L_DropDownList2:Hide() L_DropDownList3:Hide() end) end do if lib then create_DropDownButtons() end end -- ////////////////////////////////////////////////////////////// -- Global function to replace L_UIDropDownMenuTemplate function lib:Create_UIDropDownMenu(name, parent) return create_DropDownMenu(name, parent) end local function GetChild(frame, name, key) if (frame[key]) then return frame[key]; elseif name then return _G[name..key]; end return nil; end function lib:UIDropDownMenu_Initialize(frame, initFunction, displayMode, level, menuList) frame.menuList = menuList; --securecall("initializeHelper", frame); lib:UIDropDownMenu_InitializeHelper(frame) -- Set the initialize function and call it. The initFunction populates the dropdown list. if ( initFunction ) then lib:UIDropDownMenu_SetInitializeFunction(frame, initFunction); initFunction(frame, level, frame.menuList); end --master frame if(level == nil) then level = 1; end local dropDownList = _G["L_DropDownList"..level]; dropDownList.dropdown = frame; dropDownList.shouldRefresh = true; lib:UIDropDownMenu_SetDisplayMode(frame, displayMode); end function lib:UIDropDownMenu_SetInitializeFunction(frame, initFunction) frame.initialize = initFunction; end function lib:UIDropDownMenu_SetDisplayMode(frame, displayMode) -- Change appearance based on the displayMode -- Note: this is a one time change based on previous behavior. if ( displayMode == "MENU" ) then local name = frame:GetName(); GetChild(frame, name, "Left"):Hide(); GetChild(frame, name, "Middle"):Hide(); GetChild(frame, name, "Right"):Hide(); local button = GetChild(frame, name, "Button"); local buttonName = button:GetName(); GetChild(button, buttonName, "NormalTexture"):SetTexture(nil); GetChild(button, buttonName, "DisabledTexture"):SetTexture(nil); GetChild(button, buttonName, "PushedTexture"):SetTexture(nil); GetChild(button, buttonName, "HighlightTexture"):SetTexture(nil); local text = GetChild(frame, name, "Text"); button:ClearAllPoints(); button:SetPoint("LEFT", text, "LEFT", -9, 0); button:SetPoint("RIGHT", text, "RIGHT", 6, 0); frame.displayMode = "MENU"; end end function lib:UIDropDownMenu_SetFrameStrata(frame, frameStrata) frame.listFrameStrata = frameStrata; end function lib:UIDropDownMenu_RefreshDropDownSize(self) self.maxWidth = lib:UIDropDownMenu_GetMaxButtonWidth(self); self:SetWidth(self.maxWidth + 25); for i=1, L_UIDROPDOWNMENU_MAXBUTTONS, 1 do local icon = _G[self:GetName().."Button"..i.."Icon"]; if ( icon.tFitDropDownSizeX ) then icon:SetWidth(self.maxWidth - 5); end end end -- Start the countdown on a frame function lib:UIDropDownMenu_StartCounting(frame) if ( frame.parent ) then lib:UIDropDownMenu_StartCounting(frame.parent); else frame.showTimer = L_UIDROPDOWNMENU_SHOW_TIME; frame.isCounting = 1; end end -- Stop the countdown on a frame function lib:UIDropDownMenu_StopCounting(frame) if ( frame.parent ) then lib:UIDropDownMenu_StopCounting(frame.parent); else frame.isCounting = nil; end end --[[ List of button attributes ====================================================== info.text = [STRING] -- The text of the button info.value = [ANYTHING] -- The value that L_UIDROPDOWNMENU_MENU_VALUE is set to when the button is clicked info.func = [function()] -- The function that is called when you click the button info.checked = [nil, true, function] -- Check the button if true or function returns true info.isNotRadio = [nil, true] -- Check the button uses radial image if false check box image if true info.isTitle = [nil, true] -- If it's a title the button is disabled and the font color is set to yellow info.disabled = [nil, true] -- Disable the button and show an invisible button that still traps the mouseover event so menu doesn't time out info.tooltipWhileDisabled = [nil, 1] -- Show the tooltip, even when the button is disabled. info.hasArrow = [nil, true] -- Show the expand arrow for multilevel menus info.arrowXOffset = [nil, NUMBER] -- Number of pixels to shift the button's icon to the left or right (positive numbers shift right, negative numbers shift left). info.hasColorSwatch = [nil, true] -- Show color swatch or not, for color selection info.r = [1 - 255] -- Red color value of the color swatch info.g = [1 - 255] -- Green color value of the color swatch info.b = [1 - 255] -- Blue color value of the color swatch info.colorCode = [STRING] -- "|cAARRGGBB" embedded hex value of the button text color. Only used when button is enabled info.swatchFunc = [function()] -- Function called by the color picker on color change info.hasOpacity = [nil, 1] -- Show the opacity slider on the colorpicker frame info.opacity = [0.0 - 1.0] -- Percentatge of the opacity, 1.0 is fully shown, 0 is transparent info.opacityFunc = [function()] -- Function called by the opacity slider when you change its value info.cancelFunc = [function(previousValues)] -- Function called by the colorpicker when you click the cancel button (it takes the previous values as its argument) info.notClickable = [nil, 1] -- Disable the button and color the font white info.notCheckable = [nil, 1] -- Shrink the size of the buttons and don't display a check box info.owner = [Frame] -- Dropdown frame that "owns" the current dropdownlist info.keepShownOnClick = [nil, 1] -- Don't hide the dropdownlist after a button is clicked info.tooltipTitle = [nil, STRING] -- Title of the tooltip shown on mouseover info.tooltipText = [nil, STRING] -- Text of the tooltip shown on mouseover info.tooltipWarning = [nil, STRING] -- Warning-style text of the tooltip shown on mouseover info.tooltipInstruction = [nil, STRING] -- Instruction-style text of the tooltip shown on mouseover info.tooltipOnButton = [nil, 1] -- Show the tooltip attached to the button instead of as a Newbie tooltip. info.tooltipBackdropStyle = [nil, TABLE] -- Optional Backdrop style of the tooltip shown on mouseover info.justifyH = [nil, "CENTER"] -- Justify button text info.arg1 = [ANYTHING] -- This is the first argument used by info.func info.arg2 = [ANYTHING] -- This is the second argument used by info.func info.fontObject = [FONT] -- font object replacement for Normal and Highlight info.menuList = [TABLE] -- This contains an array of info tables to be displayed as a child menu info.menuListDisplayMode = [nil, "MENU"] -- If menuList is set, show the sub drop down with an override display mode. info.noClickSound = [nil, 1] -- Set to 1 to suppress the sound when clicking the button. The sound only plays if .func is set. info.padding = [nil, NUMBER] -- Number of pixels to pad the text on the right side info.topPadding = [nil, NUMBER] -- Extra spacing between buttons. info.leftPadding = [nil, NUMBER] -- Number of pixels to pad the button on the left side info.minWidth = [nil, NUMBER] -- Minimum width for this line info.customFrame = frame -- Allows this button to be a completely custom frame, should inherit from UIDropDownCustomMenuEntryTemplate and override appropriate methods. info.icon = [TEXTURE] -- An icon for the button. info.iconXOffset = [nil, NUMBER] -- Number of pixels to shift the button's icon to the left or right (positive numbers shift right, negative numbers shift left). info.iconTooltipTitle = [nil, STRING] -- Title of the tooltip shown on icon mouseover info.iconTooltipText = [nil, STRING] -- Text of the tooltip shown on icon mouseover info.iconTooltipBackdropStyle = [nil, TABLE] -- Optional Backdrop style of the tooltip shown on icon mouseover info.mouseOverIcon = [TEXTURE] -- An override icon when a button is moused over. info.ignoreAsMenuSelection [nil, true] -- Never set the menu text/icon to this, even when this button is checked info.registerForRightClick [nil, true] -- Register dropdown buttons for right clicks info.registerForAnyClick [nil, true] -- Register dropdown buttons for any clicks ]] -- Create (return) empty table function lib:UIDropDownMenu_CreateInfo() return {}; end function lib:UIDropDownMenu_CreateFrames(level, index) while ( level > L_UIDROPDOWNMENU_MAXLEVELS ) do L_UIDROPDOWNMENU_MAXLEVELS = L_UIDROPDOWNMENU_MAXLEVELS + 1; --local newList = CreateFrame("Button", "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS, nil, "L_UIDropDownListTemplate"); local newList = creatre_DropDownList("L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS) newList:SetFrameStrata("FULLSCREEN_DIALOG"); newList:SetToplevel(true); newList:Hide(); newList:SetID(L_UIDROPDOWNMENU_MAXLEVELS); newList:SetWidth(180) newList:SetHeight(10) -- for i = WoWRetail and 1 or (L_UIDROPDOWNMENU_MINBUTTONS+1), L_UIDROPDOWNMENU_MAXBUTTONS do for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do --local newButton = CreateFrame("Button", "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS.."Button"..i, newList, "L_UIDropDownMenuButtonTemplate"); local newButton = create_MenuButton("L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS.."Button"..i, newList) newButton:SetID(i); end end while ( index > L_UIDROPDOWNMENU_MAXBUTTONS ) do L_UIDROPDOWNMENU_MAXBUTTONS = L_UIDROPDOWNMENU_MAXBUTTONS + 1; for i=1, L_UIDROPDOWNMENU_MAXLEVELS do --local newButton = CreateFrame("Button", "L_DropDownList"..i.."Button"..L_UIDROPDOWNMENU_MAXBUTTONS, _G["L_DropDownList"..i], "L_UIDropDownMenuButtonTemplate"); local newButton = create_MenuButton("L_DropDownList"..i.."Button"..L_UIDROPDOWNMENU_MAXBUTTONS, _G["L_DropDownList"..i]) newButton:SetID(L_UIDROPDOWNMENU_MAXBUTTONS); end end end function lib:UIDropDownMenu_AddSeparator(level) local separatorInfo = { hasArrow = false; dist = 0; isTitle = true; isUninteractable = true; notCheckable = true; iconOnly = true; icon = "Interface\\Common\\UI-TooltipDivider-Transparent"; tCoordLeft = 0; tCoordRight = 1; tCoordTop = 0; tCoordBottom = 1; tSizeX = 0; tSizeY = 8; tFitDropDownSizeX = true; iconInfo = { tCoordLeft = 0, tCoordRight = 1, tCoordTop = 0, tCoordBottom = 1, tSizeX = 0, tSizeY = 8, tFitDropDownSizeX = true }, }; lib:UIDropDownMenu_AddButton(separatorInfo, level); end function lib:UIDropDownMenu_AddSpace(level) local spaceInfo = { hasArrow = false, dist = 0, isTitle = true, isUninteractable = true, notCheckable = true, }; lib:UIDropDownMenu_AddButton(spaceInfo, level); end function lib:UIDropDownMenu_AddButton(info, level) --[[ Might to uncomment this if there are performance issues if ( not L_UIDROPDOWNMENU_OPEN_MENU ) then return; end ]] if ( not level ) then level = 1; end local listFrame = _G["L_DropDownList"..level]; local index; if (listFrame) then index = listFrame.numButtons and (listFrame.numButtons + 1) or 1 else index = 0 end --local index = listFrame and (listFrame.numButtons + 1) or 1; local width; delegateFrame:SetAttribute("createframes-level", level); delegateFrame:SetAttribute("createframes-index", index); delegateFrame:SetAttribute("createframes", true); listFrame = listFrame or _G["L_DropDownList"..level]; local listFrameName = listFrame:GetName(); -- Set the number of buttons in the listframe listFrame.numButtons = index; local button = _G[listFrameName.."Button"..index]; local normalText = _G[button:GetName().."NormalText"]; local icon = _G[button:GetName().."Icon"]; -- This button is used to capture the mouse OnEnter/OnLeave events if the dropdown button is disabled, since a disabled button doesn't receive any events -- This is used specifically for drop down menu time outs local invisibleButton = _G[button:GetName().."InvisibleButton"]; -- Default settings button:SetDisabledFontObject(GameFontDisableSmallLeft); invisibleButton:Hide(); button:Enable(); if ( info.registerForAnyClick ) then button:RegisterForClicks("AnyUp"); elseif ( info.registerForRightClick ) then button:RegisterForClicks("LeftButtonUp", "RightButtonUp"); else button:RegisterForClicks("LeftButtonUp"); end -- If not clickable then disable the button and set it white if ( info.notClickable ) then info.disabled = true; button:SetDisabledFontObject(GameFontHighlightSmallLeft); end -- Set the text color and disable it if its a title if ( info.isTitle ) then info.disabled = true; button:SetDisabledFontObject(GameFontNormalSmallLeft); end -- Disable the button if disabled and turn off the color code if ( info.disabled ) then button:Disable(); invisibleButton:Show(); info.colorCode = nil; end -- If there is a color for a disabled line, set it if( info.disablecolor ) then info.colorCode = info.disablecolor; end -- Configure button if ( info.text ) then -- look for inline color code this is only if the button is enabled if ( info.colorCode ) then button:SetText(info.colorCode..info.text.."|r"); else button:SetText(info.text); end -- Set icon if ( info.icon or info.mouseOverIcon ) then icon:SetSize(16,16); if (WoWRetail) then if(info.icon and C_Texture.GetAtlasInfo(info.icon)) then icon:SetAtlas(info.icon); else icon:SetTexture(info.icon); end icon:ClearAllPoints(); icon:SetPoint("RIGHT", info.iconXOffset or 0, 0); else icon:SetTexture(info.icon); icon:ClearAllPoints(); icon:SetPoint("RIGHT"); end if ( info.tCoordLeft ) then icon:SetTexCoord(info.tCoordLeft, info.tCoordRight, info.tCoordTop, info.tCoordBottom); else icon:SetTexCoord(0, 1, 0, 1); end icon:Show(); else icon:Hide(); end -- Check to see if there is a replacement font if ( info.fontObject ) then button:SetNormalFontObject(info.fontObject); button:SetHighlightFontObject(info.fontObject); else button:SetNormalFontObject(GameFontHighlightSmallLeft); button:SetHighlightFontObject(GameFontHighlightSmallLeft); end else button:SetText(""); icon:Hide(); end button.iconOnly = nil; button.icon = nil; button.iconInfo = nil; if (info.iconInfo) then icon.tFitDropDownSizeX = info.iconInfo.tFitDropDownSizeX; else icon.tFitDropDownSizeX = nil; end if (info.iconOnly and info.icon) then button.iconOnly = true; button.icon = info.icon; button.iconInfo = info.iconInfo; lib:UIDropDownMenu_SetIconImage(icon, info.icon, info.iconInfo); icon:ClearAllPoints(); icon:SetPoint("LEFT"); end -- Pass through attributes button.func = info.func; button.funcOnEnter = info.funcOnEnter; button.funcOnLeave = info.funcOnLeave; if (WoWRetail) then button.iconXOffset = info.iconXOffset; button.ignoreAsMenuSelection = info.ignoreAsMenuSelection; else button.classicChecks = info.classicChecks; end button.owner = info.owner; button.hasOpacity = info.hasOpacity; button.opacity = info.opacity; button.opacityFunc = info.opacityFunc; button.cancelFunc = info.cancelFunc; button.swatchFunc = info.swatchFunc; button.keepShownOnClick = info.keepShownOnClick; button.tooltipTitle = info.tooltipTitle; button.tooltipText = info.tooltipText; button.tooltipInstruction = info.tooltipInstruction; button.tooltipWarning = info.tooltipWarning; button.arg1 = info.arg1; button.arg2 = info.arg2; button.hasArrow = info.hasArrow; button.arrowXOffset = info.arrowXOffset; button.hasColorSwatch = info.hasColorSwatch; button.notCheckable = info.notCheckable; button.menuList = info.menuList; button.menuListDisplayMode = info.menuListDisplayMode; button.tooltipWhileDisabled = info.tooltipWhileDisabled; button.noTooltipWhileEnabled = info.noTooltipWhileEnabled; button.tooltipOnButton = info.tooltipOnButton; button.noClickSound = info.noClickSound; button.padding = info.padding; button.icon = info.icon; button.mouseOverIcon = info.mouseOverIcon; if (WoWRetail) then button.tooltipBackdropStyle = info.tooltipBackdropStyle; button.iconTooltipTitle = info.iconTooltipTitle; button.iconTooltipText = info.iconTooltipText; button.iconTooltipBackdropStyle = info.iconTooltipBackdropStyle; button.iconXOffset = info.iconXOffset; button.ignoreAsMenuSelection = info.ignoreAsMenuSelection; else button.classicChecks = info.classicChecks; end if ( info.value ~= nil ) then button.value = info.value; elseif ( info.text ) then button.value = info.text; else button.value = nil; end local expandArrow = _G[listFrameName.."Button"..index.."ExpandArrow"]; expandArrow:SetPoint("RIGHT", info.arrowXOffset or 0, 0); expandArrow:SetShown(info.hasArrow); expandArrow:SetEnabled(not info.disabled); -- If not checkable move everything over to the left to fill in the gap where the check would be local xPos = 5; local buttonHeight = (info.topPadding or 0) + L_UIDROPDOWNMENU_BUTTON_HEIGHT; local yPos = -((button:GetID() - 1) * buttonHeight) - L_UIDROPDOWNMENU_BORDER_HEIGHT; local displayInfo = normalText; if (info.iconOnly) then displayInfo = icon; end displayInfo:ClearAllPoints(); if ( info.notCheckable ) then if ( info.justifyH and info.justifyH == "CENTER" ) then displayInfo:SetPoint("CENTER", button, "CENTER", -7, 0); else displayInfo:SetPoint("LEFT", button, "LEFT", 0, 0); end xPos = xPos + 10; else xPos = xPos + 12; displayInfo:SetPoint("LEFT", button, "LEFT", 20, 0); end -- Adjust offset if displayMode is menu local frame = L_UIDROPDOWNMENU_OPEN_MENU; if ( frame and frame.displayMode == "MENU" ) then if ( not info.notCheckable ) then xPos = xPos - 6; end end -- If no open frame then set the frame to the currently initialized frame frame = frame or L_UIDROPDOWNMENU_INIT_MENU; if ( info.leftPadding ) then xPos = xPos + info.leftPadding; end button:SetPoint("TOPLEFT", button:GetParent(), "TOPLEFT", xPos, yPos); -- See if button is selected by id or name if ( frame ) then if ( lib:UIDropDownMenu_GetSelectedName(frame) ) then if ( button:GetText() == lib:UIDropDownMenu_GetSelectedName(frame) ) then info.checked = 1; end elseif ( lib:UIDropDownMenu_GetSelectedID(frame) ) then if ( button:GetID() == lib:UIDropDownMenu_GetSelectedID(frame) ) then info.checked = 1; end elseif ( lib:UIDropDownMenu_GetSelectedValue(frame) ~= nil ) then if ( button.value == lib:UIDropDownMenu_GetSelectedValue(frame) ) then info.checked = 1; end end end if not info.notCheckable then local check = _G[listFrameName.."Button"..index.."Check"]; local uncheck = _G[listFrameName.."Button"..index.."UnCheck"]; if ( info.disabled ) then check:SetDesaturated(true); check:SetAlpha(0.5); uncheck:SetDesaturated(true); uncheck:SetAlpha(0.5); else check:SetDesaturated(false); check:SetAlpha(1); uncheck:SetDesaturated(false); uncheck:SetAlpha(1); end if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then check:SetSize(16,16); uncheck:SetSize(16,16); normalText:SetPoint("LEFT", check, "RIGHT", 0, 0); end if info.customCheckIconAtlas or info.customCheckIconTexture then check:SetTexCoord(0, 1, 0, 1); uncheck:SetTexCoord(0, 1, 0, 1); if info.customCheckIconAtlas then check:SetAtlas(info.customCheckIconAtlas); uncheck:SetAtlas(info.customUncheckIconAtlas or info.customCheckIconAtlas); else check:SetTexture(info.customCheckIconTexture); uncheck:SetTexture(info.customUncheckIconTexture or info.customCheckIconTexture); end elseif info.classicChecks then check:SetTexCoord(0, 1, 0, 1); uncheck:SetTexCoord(0, 1, 0, 1); check:SetSize(24,24); uncheck:SetSize(24,24); check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check"); uncheck:SetTexture(""); normalText:SetPoint("LEFT", check, "RIGHT", L_UIDROPDOWNMENU_CLASSIC_CHECK_PADDING, 0); elseif info.isNotRadio then check:SetTexCoord(0.0, 0.5, 0.0, 0.5); check:SetTexture("Interface\\Common\\UI-DropDownRadioChecks"); uncheck:SetTexCoord(0.5, 1.0, 0.0, 0.5); uncheck:SetTexture("Interface\\Common\\UI-DropDownRadioChecks"); else check:SetTexCoord(0.0, 0.5, 0.5, 1.0); check:SetTexture("Interface\\Common\\UI-DropDownRadioChecks"); uncheck:SetTexCoord(0.5, 1.0, 0.5, 1.0); uncheck:SetTexture("Interface\\Common\\UI-DropDownRadioChecks"); end -- Checked can be a function now local checked = info.checked; if ( type(checked) == "function" ) then checked = checked(button); end -- Show the check if checked if ( checked ) then button:LockHighlight(); check:Show(); uncheck:Hide(); else button:UnlockHighlight(); check:Hide(); uncheck:Show(); end else _G[listFrameName.."Button"..index.."Check"]:Hide(); _G[listFrameName.."Button"..index.."UnCheck"]:Hide(); end button.checked = info.checked; -- If has a colorswatch, show it and vertex color it local colorSwatch = _G[listFrameName.."Button"..index.."ColorSwatch"]; if ( info.hasColorSwatch ) then if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then _G["L_DropDownList"..level.."Button"..index.."ColorSwatch".."NormalTexture"]:SetVertexColor(info.r, info.g, info.b); else _G["L_DropDownList"..level.."Button"..index.."ColorSwatch"].Color:SetVertexColor(info.r, info.g, info.b); end button.r = info.r; button.g = info.g; button.b = info.b; colorSwatch:Show(); else colorSwatch:Hide(); end lib:UIDropDownMenu_CheckAddCustomFrame(listFrame, button, info); button:SetShown(button.customFrame == nil); button.minWidth = info.minWidth; width = max(lib:UIDropDownMenu_GetButtonWidth(button), info.minWidth or 0); --Set maximum button width if ( width > (listFrame and listFrame.maxWidth or 0) ) then listFrame.maxWidth = width; end if (WoWRetail) then local customFrameCount = listFrame.customFrames and #listFrame.customFrames or 0; local height = ((index - customFrameCount) * buttonHeight) + (L_UIDROPDOWNMENU_BORDER_HEIGHT * 2); for frameIndex = 1, customFrameCount do local frame = listFrame.customFrames[frameIndex]; height = height + frame:GetPreferredEntryHeight(); end -- Set the height of the listframe listFrame:SetHeight(height); else -- Set the height of the listframe listFrame:SetHeight((index * L_UIDROPDOWNMENU_BUTTON_HEIGHT) + (L_UIDROPDOWNMENU_BORDER_HEIGHT * 2)); end return button; end function lib:UIDropDownMenu_CheckAddCustomFrame(self, button, info) local customFrame = info.customFrame; button.customFrame = customFrame; if customFrame then customFrame:SetOwningButton(button); customFrame:ClearAllPoints(); customFrame:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0); customFrame:Show(); lib:UIDropDownMenu_RegisterCustomFrame(self, customFrame); end end function lib:UIDropDownMenu_RegisterCustomFrame(self, customFrame) self.customFrames = self.customFrames or {} table.insert(self.customFrames, customFrame); end function lib:UIDropDownMenu_GetMaxButtonWidth(self) local maxWidth = 0; for i=1, self.numButtons do local button = _G[self:GetName().."Button"..i]; local width = lib:UIDropDownMenu_GetButtonWidth(button); if ( width > maxWidth ) then maxWidth = width; end end return maxWidth; end function lib:UIDropDownMenu_GetButtonWidth(button) local minWidth = button.minWidth or 0; if button.customFrame and button.customFrame:IsShown() then return math.max(minWidth, button.customFrame:GetPreferredEntryWidth()); end if not button:IsShown() then return 0; end local width; local buttonName = button:GetName(); local icon = _G[buttonName.."Icon"]; local normalText = _G[buttonName.."NormalText"]; if ( button.iconOnly and icon ) then width = icon:GetWidth(); elseif ( normalText and normalText:GetText() ) then width = normalText:GetWidth() + 40; if ( button.icon ) then -- Add padding for the icon width = width + 10; end if ( button.classicChecks ) then width = width + L_UIDROPDOWNMENU_CLASSIC_CHECK_PADDING; end else return minWidth; end -- Add padding if has and expand arrow or color swatch if ( button.hasArrow or button.hasColorSwatch ) then width = width + 10; end if ( button.notCheckable ) then width = width - 30; end if ( button.padding ) then width = width + button.padding; end return math.max(minWidth, width); end function lib:UIDropDownMenu_Refresh(frame, useValue, dropdownLevel) local maxWidth = 0; local somethingChecked = nil; if ( not dropdownLevel ) then dropdownLevel = L_UIDROPDOWNMENU_MENU_LEVEL; end local listFrame = _G["L_DropDownList"..dropdownLevel]; listFrame.numButtons = listFrame.numButtons or 0; -- Just redraws the existing menu for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do local button = _G["L_DropDownList"..dropdownLevel.."Button"..i]; local checked = nil; if(i <= listFrame.numButtons) then -- See if checked or not if ( lib:UIDropDownMenu_GetSelectedName(frame) ) then if ( button:GetText() == lib:UIDropDownMenu_GetSelectedName(frame) ) then checked = 1; end elseif ( lib:UIDropDownMenu_GetSelectedID(frame) ) then if ( button:GetID() == lib:UIDropDownMenu_GetSelectedID(frame) ) then checked = 1; end elseif ( lib:UIDropDownMenu_GetSelectedValue(frame) ) then if ( button.value == lib:UIDropDownMenu_GetSelectedValue(frame) ) then checked = 1; end end end if (button.checked and type(button.checked) == "function") then checked = button.checked(button); end if not button.notCheckable and button:IsShown() then -- If checked show check image local checkImage = _G["L_DropDownList"..dropdownLevel.."Button"..i.."Check"]; local uncheckImage = _G["L_DropDownList"..dropdownLevel.."Button"..i.."UnCheck"]; if ( checked ) then if not button.ignoreAsMenuSelection then somethingChecked = true; local icon = GetChild(frame, frame:GetName(), "Icon"); if (button.iconOnly and icon and button.icon) then lib:UIDropDownMenu_SetIconImage(icon, button.icon, button.iconInfo); elseif ( useValue ) then lib:UIDropDownMenu_SetText(frame, button.value); icon:Hide(); else lib:UIDropDownMenu_SetText(frame, button:GetText()); icon:Hide(); end end button:LockHighlight(); checkImage:Show(); uncheckImage:Hide(); else button:UnlockHighlight(); checkImage:Hide(); uncheckImage:Show(); end end if ( button:IsShown() ) then local width = lib:UIDropDownMenu_GetButtonWidth(button); if ( width > maxWidth ) then maxWidth = width; end end end if(somethingChecked == nil) then lib:UIDropDownMenu_SetText(frame, VIDEO_QUALITY_LABEL6); local icon = GetChild(frame, frame:GetName(), "Icon"); icon:Hide(); end if (not frame.noResize) then for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do local button = _G["L_DropDownList"..dropdownLevel.."Button"..i]; button:SetWidth(maxWidth); end lib:UIDropDownMenu_RefreshDropDownSize(_G["L_DropDownList"..dropdownLevel]); end end function lib:UIDropDownMenu_RefreshAll(frame, useValue) for dropdownLevel = L_UIDROPDOWNMENU_MENU_LEVEL, 2, -1 do local listFrame = _G["L_DropDownList"..dropdownLevel]; if ( listFrame:IsShown() ) then lib:UIDropDownMenu_Refresh(frame, nil, dropdownLevel); end end -- useValue is the text on the dropdown, only needs to be set once lib:UIDropDownMenu_Refresh(frame, useValue, 1); end function lib:UIDropDownMenu_SetIconImage(icon, texture, info) icon:SetTexture(texture); if ( info.tCoordLeft ) then icon:SetTexCoord(info.tCoordLeft, info.tCoordRight, info.tCoordTop, info.tCoordBottom); else icon:SetTexCoord(0, 1, 0, 1); end if ( info.tSizeX ) then icon:SetWidth(info.tSizeX); else icon:SetWidth(16); end if ( info.tSizeY ) then icon:SetHeight(info.tSizeY); else icon:SetHeight(16); end icon:Show(); end function lib:UIDropDownMenu_SetSelectedName(frame, name, useValue) frame.selectedName = name; frame.selectedID = nil; frame.selectedValue = nil; lib:UIDropDownMenu_Refresh(frame, useValue); end function lib:UIDropDownMenu_SetSelectedValue(frame, value, useValue) -- useValue will set the value as the text, not the name frame.selectedName = nil; frame.selectedID = nil; frame.selectedValue = value; lib:UIDropDownMenu_Refresh(frame, useValue); end function lib:UIDropDownMenu_SetSelectedID(frame, id, useValue) frame.selectedID = id; frame.selectedName = nil; frame.selectedValue = nil; lib:UIDropDownMenu_Refresh(frame, useValue); end function lib:UIDropDownMenu_GetSelectedName(frame) return frame.selectedName; end function lib:UIDropDownMenu_GetSelectedID(frame) if ( frame.selectedID ) then return frame.selectedID; else -- If no explicit selectedID then try to send the id of a selected value or name --[[ local maxNum; if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then maxNum = L_UIDROPDOWNMENU_MAXBUTTONS else local listFrame = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL]; maxNum = listFrame.numButtons end for i=1, maxNum do]] local listFrame = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL]; for i=1, listFrame.numButtons do local button = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i]; -- See if checked or not if ( lib:UIDropDownMenu_GetSelectedName(frame) ) then if ( button:GetText() == lib:UIDropDownMenu_GetSelectedName(frame) ) then return i; end elseif ( lib:UIDropDownMenu_GetSelectedValue(frame) ) then if ( button.value == lib:UIDropDownMenu_GetSelectedValue(frame) ) then return i; end end end end end function lib:UIDropDownMenu_GetSelectedValue(frame) return frame.selectedValue; end function lib:HideDropDownMenu(level) local listFrame = _G["L_DropDownList"..level]; listFrame:Hide(); end function lib:ToggleDropDownMenu(level, value, dropDownFrame, anchorName, xOffset, yOffset, menuList, button, autoHideDelay, overrideDisplayMode) if ( not level ) then level = 1; end delegateFrame:SetAttribute("createframes-level", level); delegateFrame:SetAttribute("createframes-index", 0); delegateFrame:SetAttribute("createframes", true); L_UIDROPDOWNMENU_MENU_LEVEL = level; L_UIDROPDOWNMENU_MENU_VALUE = value; local listFrameName = "L_DropDownList"..level; local listFrame = _G[listFrameName]; if (WoWRetail) then lib:UIDropDownMenu_ClearCustomFrames(listFrame); end local tempFrame; local point, relativePoint, relativeTo; if ( not dropDownFrame ) then tempFrame = button:GetParent(); else tempFrame = dropDownFrame; end if ( listFrame:IsShown() and (L_UIDROPDOWNMENU_OPEN_MENU == tempFrame) ) then listFrame:Hide(); else -- Set the dropdownframe scale local uiScale; local uiParentScale = UIParent:GetScale(); if ( GetCVar("useUIScale") == "1" ) then uiScale = tonumber(GetCVar("uiscale")); if ( uiParentScale < uiScale ) then uiScale = uiParentScale; end else uiScale = uiParentScale; end listFrame:SetScale(uiScale); -- Hide the listframe anyways since it is redrawn OnShow() listFrame:Hide(); -- Frame to anchor the dropdown menu to local anchorFrame; -- Display stuff -- Level specific stuff if ( level == 1 ) then delegateFrame:SetAttribute("openmenu", dropDownFrame); listFrame:ClearAllPoints(); -- If there's no specified anchorName then use left side of the dropdown menu if ( not anchorName ) then -- See if the anchor was set manually using setanchor if ( dropDownFrame.xOffset ) then xOffset = dropDownFrame.xOffset; end if ( dropDownFrame.yOffset ) then yOffset = dropDownFrame.yOffset; end if ( dropDownFrame.point ) then point = dropDownFrame.point; end if ( dropDownFrame.relativeTo ) then relativeTo = dropDownFrame.relativeTo; else relativeTo = GetChild(L_UIDROPDOWNMENU_OPEN_MENU, L_UIDROPDOWNMENU_OPEN_MENU:GetName(), "Left"); end if ( dropDownFrame.relativePoint ) then relativePoint = dropDownFrame.relativePoint; end elseif ( anchorName == "cursor" ) then relativeTo = nil; local cursorX, cursorY = GetCursorPosition(); cursorX = cursorX/uiScale; cursorY = cursorY/uiScale; if ( not xOffset ) then xOffset = 0; end if ( not yOffset ) then yOffset = 0; end xOffset = cursorX + xOffset; yOffset = cursorY + yOffset; else -- See if the anchor was set manually using setanchor if ( dropDownFrame.xOffset ) then xOffset = dropDownFrame.xOffset; end if ( dropDownFrame.yOffset ) then yOffset = dropDownFrame.yOffset; end if ( dropDownFrame.point ) then point = dropDownFrame.point; end if ( dropDownFrame.relativeTo ) then relativeTo = dropDownFrame.relativeTo; else relativeTo = anchorName; end if ( dropDownFrame.relativePoint ) then relativePoint = dropDownFrame.relativePoint; end end if ( not xOffset or not yOffset ) then xOffset = 8; yOffset = 22; end if ( not point ) then point = "TOPLEFT"; end if ( not relativePoint ) then relativePoint = "BOTTOMLEFT"; end listFrame:SetPoint(point, relativeTo, relativePoint, xOffset, yOffset); else if ( not dropDownFrame ) then dropDownFrame = L_UIDROPDOWNMENU_OPEN_MENU; end listFrame:ClearAllPoints(); -- If this is a dropdown button, not the arrow anchor it to itself if ( strsub(button:GetParent():GetName(), 0,14) == "L_DropDownList" and strlen(button:GetParent():GetName()) == 15 ) then anchorFrame = button; else anchorFrame = button:GetParent(); end point = "TOPLEFT"; relativePoint = "TOPRIGHT"; listFrame:SetPoint(point, anchorFrame, relativePoint, 0, 0); end if dropDownFrame.hideBackdrops then _G[listFrameName.."Backdrop"]:Hide(); _G[listFrameName.."MenuBackdrop"]:Hide(); else -- Change list box appearance depending on display mode local displayMode = overrideDisplayMode or (dropDownFrame and dropDownFrame.displayMode) or nil; if ( displayMode == "MENU" ) then _G[listFrameName.."Backdrop"]:Hide(); _G[listFrameName.."MenuBackdrop"]:Show(); else _G[listFrameName.."Backdrop"]:Show(); _G[listFrameName.."MenuBackdrop"]:Hide(); end end if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then dropDownFrame.menuList = menuList; end lib:UIDropDownMenu_Initialize(dropDownFrame, dropDownFrame.initialize, nil, level, menuList); -- If no items in the drop down don't show it if ( listFrame.numButtons == 0 ) then return; end if (WoWRetail) then listFrame.onShow = dropDownFrame.listFrameOnShow; end -- Check to see if the dropdownlist is off the screen, if it is anchor it to the top of the dropdown button listFrame:Show(); -- Hack since GetCenter() is returning coords relative to 1024x768 local x, y = listFrame:GetCenter(); -- Hack will fix this in next revision of dropdowns if ( not x or not y ) then listFrame:Hide(); return; end listFrame.onHide = dropDownFrame.onHide; -- Set the listframe frameStrata if dropDownFrame.listFrameStrata then listFrame.baseFrameStrata = listFrame:GetFrameStrata(); listFrame:SetFrameStrata(dropDownFrame.listFrameStrata); end -- We just move level 1 enough to keep it on the screen. We don't necessarily change the anchors. if ( level == 1 ) then local offLeft = listFrame:GetLeft()/uiScale; local offRight = (GetScreenWidth() - listFrame:GetRight())/uiScale; local offTop = (GetScreenHeight() - listFrame:GetTop())/uiScale; local offBottom = listFrame:GetBottom()/uiScale; local xAddOffset, yAddOffset = 0, 0; if ( offLeft < 0 ) then xAddOffset = -offLeft; elseif ( offRight < 0 ) then xAddOffset = offRight; end if ( offTop < 0 ) then yAddOffset = offTop; elseif ( offBottom < 0 ) then yAddOffset = -offBottom; end listFrame:ClearAllPoints(); if ( anchorName == "cursor" ) then listFrame:SetPoint(point, relativeTo, relativePoint, xOffset + xAddOffset, yOffset + yAddOffset); else listFrame:SetPoint(point, relativeTo, relativePoint, xOffset + xAddOffset, yOffset + yAddOffset); end else -- Determine whether the menu is off the screen or not local offscreenY, offscreenX; if ( (y - listFrame:GetHeight()/2) < 0 ) then offscreenY = 1; end if ( listFrame:GetRight() > GetScreenWidth() ) then offscreenX = 1; end if ( offscreenY and offscreenX ) then point = gsub(point, "TOP(.*)", "BOTTOM%1"); point = gsub(point, "(.*)LEFT", "%1RIGHT"); relativePoint = gsub(relativePoint, "TOP(.*)", "BOTTOM%1"); relativePoint = gsub(relativePoint, "(.*)RIGHT", "%1LEFT"); xOffset = -11; yOffset = -14; elseif ( offscreenY ) then point = gsub(point, "TOP(.*)", "BOTTOM%1"); relativePoint = gsub(relativePoint, "TOP(.*)", "BOTTOM%1"); xOffset = 0; yOffset = -14; elseif ( offscreenX ) then point = gsub(point, "(.*)LEFT", "%1RIGHT"); relativePoint = gsub(relativePoint, "(.*)RIGHT", "%1LEFT"); xOffset = -11; yOffset = 14; else xOffset = 0; yOffset = 14; end listFrame:ClearAllPoints(); listFrame.parentLevel = tonumber(strmatch(anchorFrame:GetName(), "L_DropDownList(%d+)")); listFrame.parentID = anchorFrame:GetID(); listFrame:SetPoint(point, anchorFrame, relativePoint, xOffset, yOffset); end if (WoWClassicEra or WoWClassicTBC or WoWWOTLKC) then if ( autoHideDelay and tonumber(autoHideDelay)) then listFrame.showTimer = autoHideDelay; listFrame.isCounting = 1; end end end end function lib:CloseDropDownMenus(level) if ( not level ) then level = 1; end for i=level, L_UIDROPDOWNMENU_MAXLEVELS do _G["L_DropDownList"..i]:Hide(); end -- yes, we also want to close the menus which created by built-in UIDropDownMenus for i=level, UIDROPDOWNMENU_MAXLEVELS do _G["DropDownList"..i]:Hide(); end end local function containsMouse() local result = false for i = 1, L_UIDROPDOWNMENU_MAXLEVELS do local dropdown = _G["L_DropDownList"..i]; if dropdown:IsShown() and dropdown:IsMouseOver() then result = true; end end for i = 1, UIDROPDOWNMENU_MAXLEVELS do local dropdown = _G["DropDownList"..i]; if dropdown:IsShown() and dropdown:IsMouseOver() then result = true; end end -- TeeloJubeithos: -- If the menu is open, and you click the button to close it, -- the Global Mouse Down triggers to close it, but then the MouseDown for the button triggers to open it back up again. -- I fixed this by adding a filter to the global mouse down check, don't count it if the mouse is still over the DropDownMenu's Button if L_UIDROPDOWNMENU_OPEN_MENU and L_UIDROPDOWNMENU_OPEN_MENU.Button:IsMouseOver() then result = true; end return result; end function lib:containsMouse() containsMouse() end -- GLOBAL_MOUSE_DOWN event is only available in retail, not classic function lib:UIDropDownMenu_HandleGlobalMouseEvent(button, event) if event == "GLOBAL_MOUSE_DOWN" and (button == "LeftButton" or button == "RightButton") then if not containsMouse() then lib:CloseDropDownMenus(); end end end -- hooking UIDropDownMenu_HandleGlobalMouseEvent do if lib and WoWRetail then hooksecurefunc("UIDropDownMenu_HandleGlobalMouseEvent", function(button, event) lib:UIDropDownMenu_HandleGlobalMouseEvent(button, event) end) end end function lib:UIDropDownMenu_ClearCustomFrames(self) if self.customFrames then for index, frame in ipairs(self.customFrames) do frame:Hide(); end self.customFrames = nil; end end function lib:UIDropDownMenu_MatchTextWidth(frame, minWidth, maxWidth) local frameName = frame:GetName(); local newWidth = GetChild(frame, frameName, "Text"):GetUnboundedStringWidth() + L_UIDROPDOWNMENU_DEFAULT_WIDTH_PADDING; if minWidth or maxWidth then newWidth = Clamp(newWidth, minWidth or newWidth, maxWidth or newWidth); end lib:UIDropDownMenu_SetWidth(frame, newWidth); end function lib:UIDropDownMenu_SetWidth(frame, width, padding) local frameName = frame:GetName(); GetChild(frame, frameName, "Middle"):SetWidth(width); if ( padding ) then frame:SetWidth(width + padding); else frame:SetWidth(width + L_UIDROPDOWNMENU_DEFAULT_WIDTH_PADDING + L_UIDROPDOWNMENU_DEFAULT_WIDTH_PADDING); end if ( padding ) then GetChild(frame, frameName, "Text"):SetWidth(width); else GetChild(frame, frameName, "Text"):SetWidth(width - L_UIDROPDOWNMENU_DEFAULT_WIDTH_PADDING); end frame.noResize = 1; end function lib:UIDropDownMenu_SetButtonWidth(frame, width) local frameName = frame:GetName(); if ( width == "TEXT" ) then width = GetChild(frame, frameName, "Text"):GetWidth(); end GetChild(frame, frameName, "Button"):SetWidth(width); frame.noResize = 1; end function lib:UIDropDownMenu_SetText(frame, text) local frameName = frame:GetName(); GetChild(frame, frameName, "Text"):SetText(text); end function lib:UIDropDownMenu_GetText(frame) local frameName = frame:GetName(); return GetChild(frame, frameName, "Text"):GetText(); end function lib:UIDropDownMenu_ClearAll(frame) -- Previous code refreshed the menu quite often and was a performance bottleneck frame.selectedID = nil; frame.selectedName = nil; frame.selectedValue = nil; lib:UIDropDownMenu_SetText(frame, ""); local button, checkImage, uncheckImage; for i=1, L_UIDROPDOWNMENU_MAXBUTTONS do button = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i]; button:UnlockHighlight(); checkImage = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i.."Check"]; checkImage:Hide(); uncheckImage = _G["L_DropDownList"..L_UIDROPDOWNMENU_MENU_LEVEL.."Button"..i.."UnCheck"]; uncheckImage:Hide(); end end function lib:UIDropDownMenu_JustifyText(frame, justification, customXOffset, customYOffset) local frameName = frame:GetName(); local text = GetChild(frame, frameName, "Text"); text:ClearAllPoints(); if ( justification == "LEFT" ) then text:SetPoint("LEFT", GetChild(frame, frameName, "Left"), "LEFT", customXOffset or 27, customYOffset or 2); text:SetJustifyH("LEFT"); elseif ( justification == "RIGHT" ) then text:SetPoint("RIGHT", GetChild(frame, frameName, "Right"), "RIGHT", customXOffset or -43, customYOffset or 2); text:SetJustifyH("RIGHT"); elseif ( justification == "CENTER" ) then text:SetPoint("CENTER", GetChild(frame, frameName, "Middle"), "CENTER", customXOffset or -5, customYOffset or 2); text:SetJustifyH("CENTER"); end end function lib:UIDropDownMenu_SetAnchor(dropdown, xOffset, yOffset, point, relativeTo, relativePoint) dropdown.xOffset = xOffset; dropdown.yOffset = yOffset; dropdown.point = point; dropdown.relativeTo = relativeTo; dropdown.relativePoint = relativePoint; end function lib:UIDropDownMenu_GetCurrentDropDown() if ( L_UIDROPDOWNMENU_OPEN_MENU ) then return L_UIDROPDOWNMENU_OPEN_MENU; elseif ( L_UIDROPDOWNMENU_INIT_MENU ) then return L_UIDROPDOWNMENU_INIT_MENU; end end function lib:UIDropDownMenuButton_GetChecked(self) return _G[self:GetName().."Check"]:IsShown(); end function lib:UIDropDownMenuButton_GetName(self) return _G[self:GetName().."NormalText"]:GetText(); end function lib:UIDropDownMenuButton_OpenColorPicker(self, button) securecall("CloseMenus"); if ( not button ) then button = self; end L_UIDROPDOWNMENU_MENU_VALUE = button.value; lib:OpenColorPicker(button); end function lib:UIDropDownMenu_DisableButton(level, id) lib:UIDropDownMenu_SetDropdownButtonEnabled(_G["DropDownList"..level.."Button"..id], false); end function lib:UIDropDownMenu_EnableButton(level, id) lib:UIDropDownMenu_SetDropdownButtonEnabled(_G["DropDownList"..level.."Button"..id], true); end function lib:UIDropDownMenu_SetDropdownButtonEnabled(button, enabled) if enabled then button:Enable(); else button:Disable(); end end function lib:UIDropDownMenu_SetButtonText(level, id, text, colorCode) local button = _G["L_DropDownList"..level.."Button"..id]; if ( colorCode) then button:SetText(colorCode..text.."|r"); else button:SetText(text); end end function lib:UIDropDownMenu_SetButtonNotClickable(level, id) _G["L_DropDownList"..level.."Button"..id]:SetDisabledFontObject(GameFontHighlightSmallLeft); end function lib:UIDropDownMenu_SetButtonClickable(level, id) _G["L_DropDownList"..level.."Button"..id]:SetDisabledFontObject(GameFontDisableSmallLeft); end function lib:UIDropDownMenu_DisableDropDown(dropDown) lib:UIDropDownMenu_SetDropDownEnabled(dropDown, false, disabledtooltip); end function lib:UIDropDownMenu_EnableDropDown(dropDown) lib:UIDropDownMenu_SetDropDownEnabled(dropDown, true); end function lib:UIDropDownMenu_SetDropDownEnabled(dropDown, enabled, disabledtooltip) local dropDownName = dropDown:GetName(); local label = GetChild(dropDown, dropDownName, "Label"); if label then label:SetVertexColor((enabled and NORMAL_FONT_COLOR or GRAY_FONT_COLOR):GetRGB()); end local icon = GetChild(dropDown, dropDownName, "Icon"); if icon then icon:SetVertexColor((enabled and HIGHLIGHT_FONT_COLOR or GRAY_FONT_COLOR):GetRGB()); end local text = GetChild(dropDown, dropDownName, "Text"); if text then text:SetVertexColor((enabled and HIGHLIGHT_FONT_COLOR or GRAY_FONT_COLOR):GetRGB()); end local button = GetChild(dropDown, dropDownName, "Button"); if button then button:SetEnabled(enabled); -- Clear any previously set disabledTooltip (it will be reset below if needed). if button:GetMotionScriptsWhileDisabled() then button:SetMotionScriptsWhileDisabled(false); button:SetScript("OnEnter", nil); button:SetScript("OnLeave", nil); end end if enabled then dropDown.isDisabled = nil; else dropDown.isDisabled = 1; if button then if disabledTooltip then button:SetMotionScriptsWhileDisabled(true); button:SetScript("OnEnter", function() GameTooltip:SetOwner(button, "ANCHOR_RIGHT"); GameTooltip_AddErrorLine(GameTooltip, disabledTooltip); GameTooltip:Show(); end); button:SetScript("OnLeave", GameTooltip_Hide); end end end end function lib:UIDropDownMenu_IsEnabled(dropDown) return not dropDown.isDisabled; end function lib:UIDropDownMenu_GetValue(id) --Only works if the dropdown has just been initialized, lame, I know =( local button = _G["L_DropDownList1Button"..id]; if ( button ) then return _G["L_DropDownList1Button"..id].value; else return nil; end end function lib:OpenColorPicker(info) ColorPickerFrame.func = info.swatchFunc; ColorPickerFrame.hasOpacity = info.hasOpacity; ColorPickerFrame.opacityFunc = info.opacityFunc; ColorPickerFrame.opacity = info.opacity; ColorPickerFrame.previousValues = {r = info.r, g = info.g, b = info.b, opacity = info.opacity}; ColorPickerFrame.cancelFunc = info.cancelFunc; ColorPickerFrame.extraInfo = info.extraInfo; -- This must come last, since it triggers a call to ColorPickerFrame.func() ColorPickerFrame:SetColorRGB(info.r, info.g, info.b); ShowUIPanel(ColorPickerFrame); end function lib:ColorPicker_GetPreviousValues() return ColorPickerFrame.previousValues.r, ColorPickerFrame.previousValues.g, ColorPickerFrame.previousValues.b; end -- ////////////////////////////////////////////////////////////// -- LibUIDropDownMenuTemplates -- ////////////////////////////////////////////////////////////// -- Custom dropdown buttons are instantiated by some external system. -- When calling L_UIDropDownMenu_AddButton that system sets info.customFrame to the instance of the frame it wants to place on the menu. -- The dropdown menu creates its button for the entry as it normally would, but hides all elements. The custom frame is then anchored -- to that button and assumes responsibility for all relevant dropdown menu operations. -- The hidden button will request a size that it should become from the custom frame. lib.DropDownMenuButtonMixin = {} function lib.DropDownMenuButtonMixin:OnEnter(...) ExecuteFrameScript(self:GetParent(), "OnEnter", ...); end function lib.DropDownMenuButtonMixin:OnLeave(...) ExecuteFrameScript(self:GetParent(), "OnLeave", ...); end function lib.DropDownMenuButtonMixin:OnMouseDown(button) if self:IsEnabled() then lib:ToggleDropDownMenu(nil, nil, self:GetParent()); PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); end end lib.LargeDropDownMenuButtonMixin = CreateFromMixins(lib.DropDownMenuButtonMixin); function lib.LargeDropDownMenuButtonMixin:OnMouseDown(button) if self:IsEnabled() then local parent = self:GetParent(); lib:ToggleDropDownMenu(nil, nil, parent, parent, -8, 8); PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); end end lib.DropDownExpandArrowMixin = {}; function lib.DropDownExpandArrowMixin:OnEnter() local level = self:GetParent():GetParent():GetID() + 1; lib:CloseDropDownMenus(level); if self:IsEnabled() then local listFrame = _G["L_DropDownList"..level]; if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint()) ~= self ) then lib:ToggleDropDownMenu(level, self:GetParent().value, nil, nil, nil, nil, self:GetParent().menuList, self, nil, self:GetParent().menuListDisplayMode); end end end function lib.DropDownExpandArrowMixin:OnMouseDown(button) if self:IsEnabled() then lib:ToggleDropDownMenu(self:GetParent():GetParent():GetID() + 1, self:GetParent().value, nil, nil, nil, nil, self:GetParent().menuList, self, nil, self:GetParent().menuListDisplayMode); PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON); end end lib.UIDropDownCustomMenuEntryMixin = {}; function lib.UIDropDownCustomMenuEntryMixin:GetPreferredEntryWidth() return self:GetWidth(); end function lib.UIDropDownCustomMenuEntryMixin:GetPreferredEntryHeight() return self:GetHeight(); end function lib.UIDropDownCustomMenuEntryMixin:OnSetOwningButton() -- for derived objects to implement end function lib.UIDropDownCustomMenuEntryMixin:SetOwningButton(button) self:SetParent(button:GetParent()); self.owningButton = button; self:OnSetOwningButton(); end function lib.UIDropDownCustomMenuEntryMixin:GetOwningDropdown() return self.owningButton:GetParent(); end function lib.UIDropDownCustomMenuEntryMixin:SetContextData(contextData) self.contextData = contextData; end function lib.UIDropDownCustomMenuEntryMixin:GetContextData() return self.contextData; end -- ////////////////////////////////////////////////////////////// -- L_UIDropDownCustomMenuEntryTemplate function lib:Create_UIDropDownCustomMenuEntry(name, parent) local f = _G[name] or CreateFrame("Frame", name, parent or nil) f:EnableMouse(true) f:Hide() -- I am not 100% sure if below works for replacing the mixins f:SetScript("GetPreferredEntryWidth", function(self) return self:GetWidth() end) f:SetScript("SetOwningButton", function(self, button) self:SetParent(button:GetParent()) self.owningButton = button self:OnSetOwningButton() end) f:SetScript("GetOwningDropdown", function(self) return self.owningButton:GetParent() end) f:SetScript("SetContextData", function(self, contextData) self.contextData = contextData end) f:SetScript("GetContextData", function(self) return self.contextData end) return f end -- ////////////////////////////////////////////////////////////// -- UIDropDownMenuButtonScriptTemplate -- -- TBD -- -- ////////////////////////////////////////////////////////////// -- LargeUIDropDownMenuTemplate -- -- TBD -- -- ////////////////////////////////////////////////////////////// -- EasyMenu -- Simplified Menu Display System -- This is a basic system for displaying a menu from a structure table. -- -- Args: -- menuList - menu table -- menuFrame - the UI frame to populate -- anchor - where to anchor the frame (e.g. CURSOR) -- x - x offset -- y - y offset -- displayMode - border type -- autoHideDelay - how long until the menu disappears local function easyMenu_Initialize( frame, level, menuList ) for index = 1, #menuList do local value = menuList[index] if (value.text) then value.index = index; lib:UIDropDownMenu_AddButton( value, level ); end end end function lib:EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay ) if ( displayMode == "MENU" ) then menuFrame.displayMode = displayMode; end lib:UIDropDownMenu_Initialize(menuFrame, easyMenu_Initialize, displayMode, nil, menuList); lib:ToggleDropDownMenu(1, nil, menuFrame, anchor, x, y, menuList, nil, autoHideDelay); end function lib:EasyMenu_Initialize( frame, level, menuList ) easyMenu_Initialize( frame, level, menuList ) end