WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   OnLeave & Frame (https://www.wowinterface.com/forums/showthread.php?t=54975)

gmarco 01-04-17 06:43 PM

OnLeave & Frame
 
Hi,

I was rewriting one of my addons trying to implement a custom frame instead of the standard LDB.

Everything works just fine but I was wondering if it is possible to use an onLeave codition to close it.

The skeleton code is something like this (shorter than the full code):

Lua Code:
  1. local ADDON = ...
  2.  
  3. local Menu = CreateFrame('Frame', nil, UIParent)
  4. Menu:SetClampedToScreen(true)
  5. Menu:SetSize(100,100)
  6. Menu:Hide()
  7. -- Menu:SetScript('OnLeave', OnLeave)
  8. Menu:SetBackdrop({
  9.     bgFile = "Interface/DialogFrame/UI-DialogBox-Background",
  10.     edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
  11.     tile = true, tileSize = 32, edgeSize = 16,
  12.     insets = { left = 5, right = 5, top = 5, bottom = 5 }
  13. })
  14.  
  15. local ldb = LibStub:GetLibrary("LibDataBroker-1.1")
  16. local dataobj = ldb:NewDataObject(ADDON , {
  17.     type = "data source",
  18.     icon = "Interface\\Addons\\"..ADDON.."\\icon.tga",
  19.     text = "Test Only"
  20. })
  21.  
  22. dataobj.OnClick = function(self, button)  
  23.  
  24.     if button == "LeftButton" then
  25.  
  26.         if(Menu:IsShown()) then        
  27.    
  28.             Menu:Hide()
  29.  
  30.         else
  31.            
  32.             -- position code taken from Broker_Equipment by p3lim
  33.             Menu:ClearAllPoints()
  34.             Menu:SetPoint('TOP', self, 'BOTTOM') -- temporary anchor
  35.  
  36.             local sideAnchor = ''
  37.             if(Menu:GetRight() > GetScreenWidth()) then
  38.                 sideAnchor = 'RIGHT'
  39.             elseif(Menu:GetLeft() <= 0) then
  40.                 sideAnchor = 'LEFT'
  41.             end
  42.  
  43.             Menu:ClearAllPoints()
  44.             if(Menu:GetBottom() <= 0) then
  45.                 Menu:SetPoint('BOTTOM' .. sideAnchor, self, 'TOP' .. sideAnchor)
  46.             else
  47.                 Menu:SetPoint('TOP' .. sideAnchor, self, 'BOTTOM' .. sideAnchor)
  48.             end                    
  49.             Menu:Show()
  50.            
  51.         end
  52.        
  53.     end
  54. end

I thought a simple:

Lua Code:
  1. Menu:SetScript('OnLeave', Menu:Hide())

was ok to hide the frame when not hovering on it, but I was wrong :)

So now I ask:
Is there a simple way to accomplish this and prevent the fact the frame remains open until someone clicks the bar again ?

Thanks very much for your input.

P.s.
Actually the Tooltip is this:


Vrul 01-04-17 07:25 PM

Menu:SetScript('OnLeave', Menu.Hide)

SDPhantom 01-04-17 08:45 PM

Quote:

Originally Posted by Vrul (Post 321522)
Menu:SetScript('OnLeave', Menu.Hide)

Why this works and what it does:

You're setting the frame handler to be the :Hide() metamethod. As this isn't a function call, just passing a function pointer, it loses the internal self argument. Frames just happen to push themselves as the first argument to their handlers, so everything works out anyway.

gmarco 01-05-17 12:22 AM

Hi,
thanks really so much for the reply and explanation on the differences from : and .

I have tried to implement your suggestion but I have a problem ...
Since I left click in the Data Broker to make the menu appears and it works until I hover the frame but when I touch the buttons it breaks :/

Probably the buttons are not checked as whole frame ?

Here is a gif (in loop) showing the thing:
http://s23.postimg.org/bw238gnjv/test_menu.gif

Surely is a problem of my code because I am really not so skilled in the frame management.
I post the full thing:

Lua Code:
  1. local ADDON = ...
  2.  
  3. local ActiveSpec = GetSpecialization()
  4. local ACTSPEC = {}
  5.  
  6. local fontName, fontHeight, fontFlags = GameFontNormal:GetFont()
  7. local btn = {}
  8.  
  9. local num_lines = 9
  10. local btn_o = 5
  11. local btn_h = fontHeight + 4
  12. local line_v = - btn_h
  13. local line_o = btn_o + 4
  14. local frame_w = 190
  15. local frame_h = abs(num_lines * line_v) + 10
  16. local btn_w = frame_w - btn_o - 2
  17. local line_o2 = frame_w/2
  18.  
  19. local string_format = string.format
  20.  
  21. local ldb = LibStub:GetLibrary("LibDataBroker-1.1")
  22. local dataobj = ldb:NewDataObject(ADDON, {
  23.     type = "data source",
  24.     icon = "Interface\\Icons\\INV_Misc_QuestionMark.blp",
  25.     text = "None"
  26. })
  27.  
  28. local Menu = CreateFrame('Frame', nil, UIParent)
  29. Menu:SetClampedToScreen(true)
  30. Menu:SetSize(frame_w,frame_h)
  31. Menu:Hide()
  32. Menu:SetScript('OnLeave', Menu.Hide)
  33. Menu:SetBackdrop({
  34.     bgFile = "Interface/DialogFrame/UI-DialogBox-Background",
  35.     edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
  36.     tile = true, tileSize = 32, edgeSize = 16,
  37.     insets = { left = 5, right = 5, top = 5, bottom = 5 }
  38. })
  39.  
  40. local talent_desc = Menu:CreateFontString("talent_desc")
  41. talent_desc:SetPoint("TOPLEFT", Menu,"TOPLEFT",line_o, line_v)
  42. talent_desc:SetFont(fontName, fontHeight)
  43. talent_desc:SetTextColor(1,0.8,0,1)
  44. talent_desc:SetText("Spec config: ")
  45.  
  46. local talent_value = Menu:CreateFontString("talent_value")
  47. talent_value:SetPoint("TOPLEFT", Menu,"TOPLEFT",line_o2, line_v)
  48. talent_value:SetFont(fontName, fontHeight)
  49. talent_value:SetTextColor(0,1,0,1)
  50.  
  51. local lclick_desc = Menu:CreateFontString("lclick_desc")
  52. lclick_desc:SetPoint("TOPLEFT", Menu,"TOPLEFT",line_o, 7*line_v)
  53. lclick_desc:SetFont(fontName, fontHeight)
  54. lclick_desc:SetTextColor(1,0.8,0,1)
  55. lclick_desc:SetText("Left Click: ")
  56.  
  57. local lclick_value = Menu:CreateFontString("lclick_value")
  58. lclick_value:SetPoint("TOPLEFT", Menu,"TOPLEFT",line_o2, 7*line_v)
  59. lclick_value:SetFont(fontName, fontHeight)
  60. lclick_value:SetTextColor(0,1,0,1)
  61. lclick_value:SetText("Change Spec")
  62.  
  63. local rclick_desc = Menu:CreateFontString("rclick_desc")
  64. rclick_desc:SetPoint("TOPLEFT", Menu,"TOPLEFT",line_o, 8*line_v)
  65. rclick_desc:SetFont(fontName, fontHeight)
  66. rclick_desc:SetTextColor(1,0.8,0,1)
  67. rclick_desc:SetText("Right Click: ")
  68.  
  69. local rclick_value = Menu:CreateFontString("rclick_value")
  70. rclick_value:SetPoint("TOPLEFT", Menu,"TOPLEFT",line_o2, 8*line_v)
  71. rclick_value:SetFont(fontName, fontHeight)
  72. rclick_value:SetTextColor(0,1,0,1)
  73. rclick_value:SetText("Open Talents")
  74.  
  75.  
  76. local function BuildActiveSpec()
  77.  
  78.     local ptalenttree = {}
  79.  
  80.     local ActiveSpec = GetSpecialization()
  81.     if ActiveSpec then
  82.         local id, name, description, icon, background, role = GetSpecializationInfo(ActiveSpec)
  83.         ACTSPEC = { id = id, name = name, description = description, icon = icon , background = background, role = role }
  84.     end
  85.  
  86.     for i=1, GetMaxTalentTier()  do
  87.        for j=1, 3 do
  88.             if select(4, GetTalentInfo(i,j,1)) == true then
  89.                 ptalenttree[i] = j
  90.             end
  91.        end
  92.     end
  93.  
  94.     ACTSPEC["tree"] = table.concat(ptalenttree,".")
  95. end
  96.  
  97. local function UpdateLDB()
  98.         local currentSpec = GetSpecialization()
  99.         if currentSpec ~= nil then     
  100.             local id, name, description, icon, background, role = GetSpecializationInfo(currentSpec)       
  101.             dataobj.text = name
  102.             dataobj.icon = icon    
  103.         else
  104.             dataobj.icon = "Interface\\Icons\\INV_Misc_QuestionMark.blp"
  105.             dataobj.text = "None"
  106.         end
  107. end
  108.  
  109.  
  110. local function BuildMenu()
  111.  
  112.     for index=1,GetNumSpecializations() do
  113.  
  114.         local id, name, description, icon, background, role = GetSpecializationInfo(index)
  115.        
  116.         btn[index]=CreateFrame("Button", nil, Menu)
  117.         btn[index]:SetPoint("TOP", btn_o, -20 + (index * line_v))
  118.         btn[index]:SetWidth(btn_w)
  119.         btn[index]:SetHeight(btn_h)
  120.         btn[index]:SetNormalFontObject("GameFontNormal")
  121.         btn[index]:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
  122.            
  123.         local text = btn[index]:CreateFontString(ADDON .. "btn_font", nil, "GameFontNormal")
  124.         text:SetAllPoints(true)
  125.         text:SetJustifyH("LEFT")
  126.         text:SetJustifyV("MIDDLE")
  127.         text:SetTextColor(1,1,1,1)
  128.         btn[index]:SetFontString(text);
  129.         btn[index]:SetText(string.format("|T%s:0|t %s",icon,name))
  130.         btn[index]:SetScript("OnClick",  
  131.         function()
  132.             Menu:Hide()
  133.             SetSpecialization(index)
  134.         end)
  135.     end
  136. end
  137.  
  138. local frame = CreateFrame("Frame")
  139. frame:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
  140. frame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
  141. frame:RegisterEvent("PLAYER_ENTERING_WORLD")
  142. frame:SetScript("OnEvent", function(self, event, ...)
  143.  
  144.     BuildActiveSpec()
  145.     UpdateLDB()
  146.        
  147.     if event == "PLAYER_ENTERING_WORLD" then
  148.         BuildMenu()
  149.     end
  150. end
  151. )
  152.  
  153.  
  154. function dataobj.OnClick(self, button)  
  155.  
  156.     if InCombatLockdown() then
  157.         return
  158.     end
  159.  
  160.     if button == "RightButton" then
  161.         ToggleTalentFrame()
  162.     end
  163.  
  164.     if button == "LeftButton" then
  165.  
  166.         if(Menu:IsShown()) then        
  167.    
  168.             Menu:Hide()
  169.  
  170.         else
  171.                    
  172.             talent_value:SetText(ACTSPEC["tree"])
  173.            
  174.             -- position code taken from Broker_Equipment by p3lim
  175.             Menu:ClearAllPoints()
  176.             Menu:SetPoint('TOP', self, 'BOTTOM') -- temporary anchor
  177.  
  178.             local sideAnchor = ''
  179.             if(Menu:GetRight() > GetScreenWidth()) then
  180.                 sideAnchor = 'RIGHT'
  181.             elseif(Menu:GetLeft() <= 0) then
  182.                 sideAnchor = 'LEFT'
  183.             end
  184.  
  185.             Menu:ClearAllPoints()
  186.             if(Menu:GetBottom() <= 0) then
  187.                 Menu:SetPoint('BOTTOM' .. sideAnchor, self, 'TOP' .. sideAnchor)
  188.             else
  189.                 Menu:SetPoint('TOP' .. sideAnchor, self, 'BOTTOM' .. sideAnchor)
  190.             end        
  191.            
  192.             Menu:Show()
  193.         end    
  194.     end
  195. end

Thanks all.

SDPhantom 01-07-17 04:41 AM

From what I can tell, Menu is firing OnLeave you mouseover the spec buttons. You might want to have a custom handler check for that before hiding itself. You're also recreating them at every loading screen instead of just at login. You should either unregister PLAYER_ENTERING_WORLD when done or use PLAYER_LOGIN instead.

gmarco 01-07-17 11:02 AM

Quote:

Originally Posted by SDPhantom (Post 321536)
You're also recreating them at every loading screen instead of just at login. You should either unregister PLAYER_ENTERING_WORLD when done or use PLAYER_LOGIN instead.

Thanks very much for your suggestions and hints.

About the second part of the problems I have changed in this way (I realized that it should be broken because sometime the buttons fonts were mangled).

I used a mix of your tips using event "PLAYER_LOGIN" and then unregister once fired.

Lua Code:
  1. local frame = CreateFrame("Frame")
  2. frame:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
  3. frame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
  4. frame:RegisterEvent("PLAYER_ENTERING_WORLD")
  5. frame:RegisterEvent("PLAYER_LOGIN")
  6. frame:SetScript("OnEvent", function(self, event, ...)
  7.     BuildActiveSpec()
  8.     UpdateLDB()
  9.        
  10.     if event == "PLAYER_LOGIN" then
  11.         BuildMenu()
  12.         frame:UnregisterEvent("PLAYER_LOGIN")
  13.     end
  14. end
  15. )


Quote:

Originally Posted by SDPhantom (Post 321536)
From what I can tell, Menu is firing OnLeave you mouseover the spec buttons. You might want to have a custom handler check for that before hiding itself.

Uhm ...

This works but is so ugly ?

Lua Code:
  1. Menu:SetScript('OnLeave', function()
  2.     local name = GetMouseFocus():GetName() or tostring(GetMouseFocus())
  3.     if string.sub(name,1,6) ~= "table:" then Menu:Hide() end
  4. end)

The problem is when I hovering the buttons the "name" var is something like:
table:00000149a7cf46e0

or if I exit from the frame values I get are:
WorldFrame
ChocolateBar1
etc etc ...

Thanks anyway for your suggestions.

Vrul 01-07-17 02:40 PM

Here is a modified version of your code with the OnLeave script fixed. I also changed it to behave and look more like other LDB plugins I've seen.
Code:

local ADDON = ...

local fontName, fontHeight, fontFlags = GameFontNormal:GetFont()

local BUTTON_HEIGHT = fontHeight + 4
local BUTTON_SPACING = 0
local MENU_BUFFER = 10
local MENU_SPACING = 1
local MENU_WIDTH = 190

local Menu = CreateFrame('Frame', nil, UIParent)
Menu:SetFrameStrata('TOOLTIP')
Menu:SetClampedToScreen(true)
Menu:SetBackdrop({
        bgFile = "Interface/DialogFrame/UI-DialogBox-Background",
        edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
        tile = true, tileSize = 32, edgeSize = 16,
        insets = { left = 5, right = 5, top = 5, bottom = 5 }
})
Menu:Hide()

local function Menu_OnLeave()
        local focus = GetMouseFocus() or WorldFrame
        if focus ~= Menu and focus:GetParent() ~= Menu then
                Menu:Hide()
        end
end
Menu:SetScript('OnLeave', Menu_OnLeave)

local talent_desc = Menu:CreateFontString()
talent_desc:SetPoint("TOPLEFT", Menu, "TOPLEFT", MENU_BUFFER, -MENU_BUFFER)
talent_desc:SetFont(fontName, fontHeight)
talent_desc:SetTextColor(1, 1, 1, 1)
talent_desc:SetText("Spec config:")

local talent_value = Menu:CreateFontString()
talent_value:SetPoint("TOPRIGHT", Menu, "TOPRIGHT", -MENU_BUFFER, -MENU_BUFFER)
talent_value:SetFont(fontName, fontHeight)
talent_value:SetTextColor(1, 1, 1, 1)

local rclick_desc = Menu:CreateFontString()
rclick_desc:SetPoint("BOTTOMLEFT", Menu, "BOTTOMLEFT", MENU_BUFFER, MENU_BUFFER)
rclick_desc:SetFont(fontName, fontHeight)
rclick_desc:SetTextColor(0, 1, 0, 1)
rclick_desc:SetText("Right-Click")

local rclick_value = Menu:CreateFontString()
rclick_value:SetPoint("BOTTOMRIGHT", Menu, "BOTTOMRIGHT", -MENU_BUFFER, MENU_BUFFER)
rclick_value:SetFont(fontName, fontHeight)
rclick_value:SetTextColor(1, 0.8, 0, 1)
rclick_value:SetText("Toggle Talents")

local lclick_desc = Menu:CreateFontString()
lclick_desc:SetPoint("BOTTOMLEFT", rclick_desc, "TOPLEFT", 0, MENU_SPACING)
lclick_desc:SetFont(fontName, fontHeight)
lclick_desc:SetTextColor(0, 1, 0, 1)
lclick_desc:SetText("Left-Click")

local lclick_value = Menu:CreateFontString()
lclick_value:SetPoint("BOTTOMRIGHT", rclick_value, "TOPRIGHT", 0, MENU_SPACING)
lclick_value:SetFont(fontName, fontHeight)
lclick_value:SetTextColor(1, 0.8, 0, 1)
lclick_value:SetText("Toggle Menu")

local dataobj = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject(ADDON, {
        type = "data source",
        icon = "Interface\\Icons\\INV_Misc_QuestionMark.blp",
        text = "None",
        OnClick = function(self, button)
                if button == "LeftButton" then
                        Menu:SetShown(not Menu:IsShown())
                elseif button == "RightButton" then
                        ToggleTalentFrame()
                end
        end,
        OnEnter = function(self)
                if not Menu:IsShown() then
                        local _, selfCenter = self:GetCenter()
                        local _, uiCenter = UIParent:GetCenter()
                        Menu:ClearAllPoints()
                        if selfCenter >= uiCenter then
                                Menu:SetPoint('TOP', self, 'BOTTOM')
                        else
                                Menu:SetPoint('BOTTOM', self, 'TOP')
                        end
                        Menu:Show()
                end
        end,
        OnLeave = Menu_OnLeave
})

local function EventHandler()
        local activeSpec = GetSpecialization()
        if activeSpec then
                local id, name, description, icon = GetSpecializationInfo(activeSpec)
                dataobj.text = name
                dataobj.icon = icon   
        else
                dataobj.icon = "Interface\\Icons\\INV_Misc_QuestionMark.blp"
                dataobj.text = "None"
        end

        local talents = ""
        for tier = 1, GetMaxTalentTier()  do
                local talentTier = "x"
                for column = 1, 3 do
                        local talentID, name, texture, selected = GetTalentInfo(tier, column, 1)
                        if selected then
                                talentTier = column
                                break
                        end
                end
                if talents ~= "" then
                        talents = talents .. "." .. talentTier
                else
                        talents = talentTier
                end
        end
        talent_value:SetText(talents)
end

local function Button_OnClick(self)
        Menu:Hide()
        if not InCombatLockdown() and GetSpecialization() ~= self.index then
                SetSpecialization(self.index)
        end
end

Menu:RegisterEvent('PLAYER_LOGIN')
Menu:SetScript('OnEvent', function(self, event)
        Menu:UnregisterEvent(event)
        Menu:SetScript('OnEvent', EventHandler)

        local numButtons = GetNumSpecializations()
        for index = 1, numButtons do
                local id, name, description, icon, background, role = GetSpecializationInfo(index)

                local button = CreateFrame("Button", nil, Menu)
                if index ~= 1 then
                        button:SetPoint("TOPLEFT", Menu[index - 1], "BOTTOMLEFT", 0, -BUTTON_SPACING)
                else
                        button:SetPoint("TOPLEFT", talent_desc, "BOTTOMLEFT", 0, -MENU_BUFFER)
                end
                button:SetPoint("RIGHT", -MENU_BUFFER, 0)
                button:SetHeight(BUTTON_HEIGHT)
                button:SetNormalFontObject("GameFontNormal")
                button:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
                button.index = index
                button:SetScript("OnClick", Button_OnClick)
                button:SetScript("OnLeave", Menu_OnLeave)
                Menu[index] = button

                local text = button:CreateFontString(ADDON .. "btn_font", nil, "GameFontNormal")
                text:SetAllPoints()
                text:SetJustifyH("LEFT")
                text:SetJustifyV("MIDDLE")
                text:SetTextColor(1, 1, 1, 1)
                button:SetFontString(text)
                button:SetText(("|T%s:0|t %s"):format(icon, name))
        end
        Menu:SetSize(MENU_WIDTH, (MENU_BUFFER * 4) + (fontHeight * 3) + MENU_SPACING + ((BUTTON_HEIGHT + BUTTON_SPACING) * numButtons - BUTTON_SPACING))

        EventHandler()
        Menu:RegisterEvent('PLAYER_ENTERING_WORLD')
        Menu:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
        Menu:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
end)


gmarco 01-07-17 05:25 PM

Thanks Vrul,

your code is awesome and work like a charm :)
I am studying it :)

Thanks again.
It is much appreciated.


All times are GMT -6. The time now is 12:15 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI