Quantcast UIDropDownMenu Alternatives? - WoWInterface
Thread Tools Display Modes
08-25-19, 12:52 PM   #1
mtp1032
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 20
UIDropDownMenu Alternatives?

I wrote a prototype AddOn whose options were implemented using the libs of UIDropDownMenu. I'm glad I prototyped it because I learned that the options of UIDropDownMenu cannot be refreshed. So, is there a recommended way to set up an options menu such that its options can be refreshed?

For example, suppose the character in the image below added a second bag. The second bag will not show up because UIDropDownMenu cannot be refreshed. Reloading the UI is the only alternative. Ideally, when a character adds, removes, or relocates a bag the options menu will refresh the new or moved bag will now show up as an option.

[My Addon's Options Menu]




Thanks, in advance.

Last edited by mtp1032 : 08-25-19 at 12:55 PM. Reason: Added Picture
  Reply With Quote
08-25-19, 11:31 PM   #2
Auz
A Defias Bandit
 
Auz's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2013
Posts: 3
you could use EasyMenu, you basically create your menu frame using UIDropDownMenuTemplate, then create an array with your menu options and then call the EasyMenu method passing it your frame, your array, etc. It's fairly simple to work with.

https://wow.gamepedia.com/API_EasyMenu

Code:
-- EXAMPLE --

local frame = CreateFrame("Frame", "MyFrame")
local menu = CreateFrame("Frame", "MyMenuFrame", frame , "UIDropDownMenuTemplate")
menu:SetPoint("BOTTOMRIGHT")
menu:Hide()

local menu_options = {}

local function update_menu()
    
    -- clear the menu so that it can be re-initialized
    my_menu_options = {}

    -- build the menu array
    my_menu_options = {
   		{ 
			text = "Options", 
			isTitle = true, 
			notCheckable = true,
		},
		{ 
			text = "Option One", 
			checked = false,
			func = function(self)
                            -- do something 
			end,
		},
		{ 
			text = "Option Two", 
			checked = false,
			func = function(self)
                            -- do something 
			end,
		},
			text = "More Options", 
			notCheckable = true,
			hasArrow = true,
			menuList = 
			{
				{ 
					text = "Option Three",
					checked = false,
					func = function(self)
                                          -- do something
					end, 
				},
				{ 
					text = "Option Four", 
					checked = true,
					func = function(self) 
						-- do something
					end, 
				},
                         },
                 },
          }
end

-- EasyMenu(menuList, menuFrame, anchor, x, y, displayMode, autoHideDelay)

frame:SetScript("OnClick", 
    function(self, button)
	update_menu()
	EasyMenu(menu_options, menu, frame, 0, 0, "MENU", 3)
    end
)
You put your options array inside a function and call that function before every call to EasyMenu which "refreshes" your options. that way, you can manipulate your options menu before it's shown, so your menu's don't have to be just static arrays, you can customize them on the fly if you need to.

Hope this helps

Last edited by Auz : 08-25-19 at 11:40 PM.
  Reply With Quote
08-26-19, 06:10 AM   #3
Vrul
A Rage Talon Dragon Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 312
Originally Posted by mtp1032 View Post
I'm glad I prototyped it because I learned that the options of UIDropDownMenu cannot be refreshed. So, is there a recommended way to set up an options menu such that its options can be refreshed?
I wrote LibMenuAssist to make working with UIDropDownMenu easier for me and added a few extra features that I wanted. You should be able to throw it in and use if fairly painlessly or just look at the code to see how I implemented the Refresh method and do something similar in your addon.

Originally Posted by mtp1032 View Post
The second bag will not show up because UIDropDownMenu cannot be refreshed. Reloading the UI is the only alternative.
You should only have to close and reopen your menu to get it to display changes. If that is not the case then post your code because you are not initializing your menu properly.

Last edited by Vrul : 08-26-19 at 06:17 AM.
  Reply With Quote
08-26-19, 01:46 PM   #4
mtp1032
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 20
Thank you Vrul and Auz

Vrul, I'll post my code in just a bit. Right now I'm creating names for the Classic launch.

Cheers,
  Reply With Quote
08-26-19, 02:06 PM   #5
mtp1032
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 20
When this code is executed, the player's bag slots are queried to see if they contain a bag (bg:getBag(slotNum). If a bag is not present then a checkbox is created for that bag. If not bag is installed, then no checkbox is created.

Just to recapitulate: the problem is that when the player adds, removes, or relocates a bag I would like to catch the interrupt and refresh this menu. If, for example, the player installed a new bag in slot 4, the menu would create a checkbox for that bag in slot 4 upon being refreshed.

Thanks for you time. I do appreciate it.

Lua Code:
  1. function cha:CHACHING_InitializeOptions()
  2.  
  3.     local versionString = string.format(L["ADDON_NAME_AND_VERSION"])
  4.     local ConfigurationPanel = CreateFrame("FRAME","CHACHING_MainFrame")
  5.     ConfigurationPanel.name = L["ADDON_NAME"]
  6.     InterfaceOptions_AddCategory(ConfigurationPanel)    -- Register the Configuration panel with LibUIDropDownMenu
  7.     -- Print a header at the top of the panel
  8.     local IntroMessageHeader = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormalLarge")
  9.     IntroMessageHeader:SetPoint("TOPLEFT", 10, -10)
  10.     IntroMessageHeader:SetText(versionString)
  11.  
  12.     local AuthorSubHeader = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormal")
  13.     AuthorSubHeader:SetPoint("TOPLEFT", 20, -30)
  14.     AuthorSubHeader:SetText("Author: [email protected]")
  15.  
  16.     local DescrSubHeader = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormalLarge")
  17.     DescrSubHeader:SetPoint("TOPLEFT", 20, -50)
  18.     DescrSubHeader:SetText("Enables the bulk selling of selected items in player's inventory.")
  19.        
  20.     -- Create two check buttons: one to sell grey iterms and one to sell white items
  21.     local GreyQualityButton = CreateFrame("CheckButton", "CHACHING_GreyQualityButton", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  22.     GreyQualityButton:SetPoint("TOPLEFT", 20, -80)
  23.     GreyQualityButton.tooltip = "Check to sell all poor (grey) items in your inventory."
  24.     getglobal(GreyQualityButton:GetName().."Text"):SetText("Sell Grey Items?")
  25.     GreyQualityButton:SetScript("OnClick",
  26.     function()
  27.         local isChecked = GreyQualityButton:GetChecked()
  28.         if isChecked then
  29.             sellGrey = true -- 1
  30.         else
  31.             sellGrey = false
  32.         end
  33.     end )
  34.  
  35.     local WhiteQualityButton = CreateFrame("CheckButton", "CHACHING_WhiteQualityButton", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  36.     WhiteQualityButton:SetPoint("TOPLEFT", 200, -80)
  37.     WhiteQualityButton.tooltip = L["TOOLTIP_CHECK_WHITE_BTN"]
  38.     getglobal(WhiteQualityButton:GetName().."Text"):SetText("Sell White Items (Only Armor and Weapons?")
  39.     WhiteQualityButton:SetScript("OnClick",
  40.     function()
  41.         local isChecked = WhiteQualityButton:GetChecked()
  42.         if isChecked then
  43.             sellWhite = true
  44.         else
  45.             sellWhite = false
  46.         end
  47.     end )
  48.  
  49.     -- SELECT BAG BUTTONS
  50.     local Bags = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormal")
  51.     Bags:SetPoint("TOPLEFT", 20, -200)
  52.     Bags:SetText("Select a bag. All items in the selected bag will be sold!")
  53.     local checkBoxLabel = nil
  54.     local xpos = 20
  55.     local ypos = -215
  56.     local delta_y = -20
  57.  
  58.     --**************************************************************************************************************************
  59.     --                                      BAG 1 (The player's backpack) will ALWAYS be present and available
  60.     --**************************************************************************************************************************
  61.     local bagOne = bg:getBag(0)
  62.     checkBoxLabel = string.format("Bag[1] - %s", bagOne:getName() )
  63.     local BagButtonOne = CreateFrame("CheckButton", "CHACHING_BagButtonOne", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  64.     BagButtonOne:SetPoint("TOPLEFT", xpos, ypos)
  65.     getglobal(BagButtonOne:GetName().."Text"):SetText(checkBoxLabel)
  66.        
  67.     BagButtonOne:SetScript("OnClick",
  68.     function()
  69.         local isChecked = BagButtonOne:GetChecked()
  70.         if isChecked then
  71.             isBagChecked[BAG1] = true
  72.         else
  73.             isBagChecked[BAG1] = false
  74.         end
  75.     end )
  76.    
  77.     --***************************************************************************************************************************
  78.     --                                          BAG 2
  79.     --***************************************************************************************************************************
  80.     local bagTwo = bg:getBag(1)
  81.     if bagTwo ~= nil then
  82.         checkBoxLabel = string.format("Bag[2] - %s", bagTwo:getName())
  83.            
  84.         ypos = ypos + delta_y
  85.         local BagButtonTwo = CreateFrame("CheckButton", "CHACHING_BagButtonTwo", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  86.         BagButtonTwo:SetPoint("TOPLEFT", xpos, ypos)
  87.         getglobal(BagButtonTwo:GetName().."Text"):SetText(checkBoxLabel)   
  88.  
  89.         BagButtonTwo:SetScript("OnClick",
  90.         function()
  91.             if bagTwo ~= nil then
  92.                 local isChecked = BagButtonTwo:GetChecked()
  93.                 if isChecked then
  94.                     isBagChecked[BAG2] = true
  95.                 else
  96.                     isBagChecked[BAG2] = false
  97.                 end
  98.             end
  99.         end )
  100.     end
  101.  
  102.     --**************************************************************************************************************************
  103.     --                                          BAG 3
  104.     --**************************************************************************************************************************
  105.     local bagThree = bg:getBag(2)
  106.     if bagThree ~= nil then
  107.         checkBoxLabel = string.format("Bag[3] - %s", bagThree:getName())
  108.  
  109.         ypos = ypos + delta_y
  110.         local BagButtonThree = CreateFrame("CheckButton", "CHACHING_BagButtonThree", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  111.         BagButtonThree:SetPoint("TOPLEFT", xpos, ypos)
  112.         getglobal(BagButtonThree:GetName().."Text"):SetText(checkBoxLabel)
  113.  
  114.         BagButtonThree:SetScript("OnClick",
  115.         function()
  116.             local isChecked = BagButtonThree:GetChecked()
  117.             if isChecked then
  118.                 isBagChecked[BAG3] = true
  119.             else
  120.                 isBagChecked[BAG3] = false
  121.             end
  122.         end )
  123.     end
  124.  
  125.     --**************************************************************************************************************************
  126.     --                                          BAG 4
  127.     --**************************************************************************************************************************
  128.     local bagFour = bg:getBag(3)
  129.     if bagFour ~= nil then
  130.         checkBoxLabel = string.format("Bag[4] - %s", bagFour:getName())
  131.  
  132.         ypos = ypos + delta_y
  133.         local BagButtonFour = CreateFrame("CheckButton", "CHACHING_BagButtonFour", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  134.         BagButtonFour:SetPoint("TOPLEFT", xpos, ypos)
  135.         local txt = string.format("Bag[4] - %s", bagFour:getName() )
  136.         getglobal(BagButtonFour:GetName().."Text"):SetText(txt)
  137.        
  138.         BagButtonFour:SetScript("OnClick",
  139.         function()
  140.             local isChecked = BagButtonFour:GetChecked()
  141.             if isChecked then
  142.                 isBagChecked[BAG4] = true
  143.             else
  144.                 isBagChecked[BAG4] = false
  145.             end
  146.         end )
  147.     end
  148.  
  149.     --**************************************************************************************************************************
  150.     --                                          BAG 5
  151.     --**************************************************************************************************************************
  152.     local bagFive = bg:getBag(4)
  153.     if bagFive ~= nil then
  154.         checkBoxLabel = string.format("Bag[5] - %s", bagFive:getName())
  155.        
  156.         ypos = ypos + delta_y
  157.         local BagButtonFive = CreateFrame("CheckButton", "CHACHING_BagButtonFive", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
  158.         BagButtonFive:SetPoint("TOPLEFT", xpos, ypos)
  159.         getglobal(BagButtonFive:GetName().."Text"):SetText(checkBoxLabel)
  160.        
  161.         BagButtonFive:SetScript("OnClick",
  162.         function()
  163.             local isChecked = BagButtonFive:GetChecked()
  164.             if isChecked then
  165.                 isBagChecked[BAG5] = true
  166.             else
  167.                 isBagChecked[BAG5] = false
  168.             end
  169.         end )
  170.     end
  171.  
  172.     local readmeMsg1 = string.format("                    *** IMPORTANT ***                               \n")
  173.     local readmeMsg2 = string.format("The merchant buyback window only has 12 slots. However, the merchant\n")
  174.     local readmeMsg3 = string.format("will buy as many items as Cha-Ching is configured to sell. So, if more\n")
  175.     local readmeMsg4 = string.format("than 12 items were sold, you will only be able to buyback the last 12\n")
  176.    
  177.     local ReadmeMessageTitle = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormalLarge")
  178.     ReadmeMessageTitle:SetPoint("TOPLEFT", 10, -280)
  179.     ReadmeMessageTitle:SetText(readmeMsg1..readmeMsg2..readmeMsg3..readmeMsg4 )
  180. end
  Reply With Quote
08-27-19, 06:19 AM   #6
Vrul
A Rage Talon Dragon Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 312
I thought you said you were using UIDropDownMenu but I don't see that anywhere in the code provided. That code should only be run once so of course it won't automatically update itself.

Not sure when, but when I get some time I'll clean it up and add what you need to update the bag check boxes.
  Reply With Quote
08-27-19, 01:22 PM   #7
Vrul
A Rage Talon Dragon Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 312
I changed your buttons names from "CHACHING_BagButtonOne" to "CHACHING_BagButton1" and similarly changed isBagChecked[BAG1] to isBagChecked[1] (repeat for 2 through 5). This should look how you originally had it:
Code:
function cha:CHACHING_InitializeOptions()
 
    local ConfigurationPanel = CreateFrame("FRAME","CHACHING_MainFrame")
    ConfigurationPanel.name = L["ADDON_NAME"]
    InterfaceOptions_AddCategory(ConfigurationPanel)    -- Register the Configuration panel with LibUIDropDownMenu

    -- Print a header at the top of the panel
    local IntroMessageHeader = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormalLarge")
    IntroMessageHeader:SetPoint("TOPLEFT", 10, -10)
    IntroMessageHeader:SetText(L["ADDON_NAME_AND_VERSION"])
 
    local AuthorSubHeader = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormal")
    AuthorSubHeader:SetPoint("TOPLEFT", 20, -30)
    AuthorSubHeader:SetText("Author: [email protected]")
 
    local DescrSubHeader = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormalLarge")
    DescrSubHeader:SetPoint("TOPLEFT", 20, -50)
    DescrSubHeader:SetText("Enables the bulk selling of selected items in player's inventory.")
        
    local ReadmeMessageText = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormalLarge")
    ReadmeMessageText:SetPoint("TOPLEFT", 10, -280)
    ReadmeMessageText:SetText(strjoin("\n",
        "                    *** IMPORTANT ***                               ",
        "The merchant buyback window only has 12 slots. However, the merchant",
        "will buy as many items as Cha-Ching is configured to sell. So, if more",
        "than 12 items were sold, you will only be able to buyback the last 12"
    ))

    -- Create check button to sell grey items
    local GreyQualityButton = CreateFrame("CheckButton", "CHACHING_GreyQualityButton", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
    GreyQualityButton:SetPoint("TOPLEFT", 20, -80)
    GreyQualityButton.tooltip = "Check to sell all poor (grey) items in your inventory."
    _G[GreyQualityButton:GetName().."Text"]:SetText("Sell Grey Items?")
    GreyQualityButton:SetScript("OnClick", function(self)
        sellGrey = self:GetChecked() and true or false
    end)
 
    -- Create check button to sell white items
    local WhiteQualityButton = CreateFrame("CheckButton", "CHACHING_WhiteQualityButton", ConfigurationPanel, "ChatConfigCheckButtonTemplate")
    WhiteQualityButton:SetPoint("TOPLEFT", 200, -80)
    WhiteQualityButton.tooltip = L["TOOLTIP_CHECK_WHITE_BTN"]
    _G[WhiteQualityButton:GetName().."Text"]:SetText("Sell White Items (Only Armor and Weapons?")
    WhiteQualityButton:SetScript("OnClick", function(self)
        sellWhite = self:GetChecked() and true or false
    end)
 
    -- Create bag select buttons
    local bagsText = ConfigurationPanel:CreateFontString(nil, "ARTWORK","GameFontNormal")
    bagsText:SetPoint("TOPLEFT", 20, -200)
    bagsText:SetText("Select a bag. All items in the selected bag will be sold!")

    local xpos = 20
    local ypos = -215
    local delta_y = -20

    local function BagSelectButtonOnClick(self)
        isBagChecked[self.bagIndex] = self:GetChecked() and true or false
    end

    local bagSelectButtons = { } 
    for id = 0, 4 do
        local bagIndex = id + 1
        local button = CreateFrame("CheckButton", "CHACHING_BagButton" .. bagIndex, ConfigurationPanel, "ChatConfigCheckButtonTemplate")
        button:SetPoint("TOPLEFT", xpos, ypos + (delta_y * id))
        button.label = _G[button:GetName() .. "Text"]
        button.bagIndex = bagIndex
        button:SetScript("OnClick", BagSelectButtonOnClick)
        bagSelectButtons[bagIndex] = button
    end

    local function UpdateBagSelectButtons()
        local index = 0
        for id = 0, 4 do
            if GetContainerNumSlots(id) > 0 then
                index = index + 1
                local button = bagSelectButtons[index]
                button.bagIndex = id + 1
                button.label:SetText(("Bag[%s] - %s"):format(button.bagIndex, GetBagName(id)))
                button:Show()
            end
        end
        for index = index + 1, #bagSelectButtons do
            bagSelectButtons[index]:Hide()
        end
    end

    ConfigurationPanel:SetScript("OnEvent", UpdateBagSelectButtons)

    ConfigurationPanel:SetScript("OnHide", function(self)
        self:UnregisterEvent("BAG_UPDATE")
    end)

    ConfigurationPanel:SetScript("OnShow", function(self)
        self:RegisterEvent("BAG_UPDATE")
        UpdateBagSelectButtons()
    end)

end
If you replace the UpdateBagSelectButtons function with this then all the buttons will remain showing but just enable/disable as needed (along with updating their labels):
Code:
    local function UpdateBagSelectButtons()
        for id = 0, 4 do
            local button = bagSelectButtons[id + 1]
            if GetContainerNumSlots(id) > 0 then
                button.label:SetText(("Bag[%s] - %s"):format(button.bagIndex, GetBagName(id)))
                button:SetEnabled(true)
            else
                button.label:SetText(("Bag[%s]"):format(button.bagIndex))
                button:SetEnabled(false)
            end
        end
    end
Caveat: Code untested and may contain typos
  Reply With Quote
09-08-19, 06:48 PM   #8
mtp1032
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 20
Thanks.

I'm truly sorry I didn't get back to you earlier. I was called away for a couple of weeks and just didn't have the time. I'll study your code/suggestions and incorporate them into Chaching. I'll let you know how it works out.

Again, I deeply appreciate your time.

UPDATE:

Seems to work just fine. There is a minor issue in that the bag names are not displayed when the addon is called for the first time. It's a problem I need to work on because I want to learn this stuff. So, again, thank you for your time.

Last edited by mtp1032 : 09-09-19 at 10:53 AM. Reason: Follow up
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » UIDropDownMenu Alternatives?

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off