Thread Tools Display Modes
01-04-17, 06:43 PM   #1
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
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:

__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
01-04-17, 07:25 PM   #2
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Menu:SetScript('OnLeave', Menu.Hide)
  Reply With Quote
01-04-17, 08:45 PM   #3
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by Vrul View Post
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
01-05-17, 12:22 AM   #4
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
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.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
01-07-17, 04:41 AM   #5
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
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.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
01-07-17, 11:02 AM   #6
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Originally Posted by SDPhantom View Post
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. )


Originally Posted by SDPhantom View Post
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.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
01-07-17, 02:40 PM   #7
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
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)
  Reply With Quote
01-07-17, 05:25 PM   #8
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Thanks Vrul,

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

Thanks again.
It is much appreciated.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » OnLeave & Frame

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