Quantcast Remove a Frame element with LUA - WoWInterface
Thread Tools Display Modes
10-28-09, 08:30 PM   #1
richardCANE
A Murloc Raider
Join Date: Oct 2009
Posts: 5
Remove a Frame element with LUA

hi guys

i want to create a frame that shows your main bag's content with icons too...

so when i open up my addon frame the LUA dynamically draws a frame and draws the CURRENT content of my bag into...

is it possible to remove/delete/clear frames, textures and fontstrings ( xml elements ) with LUA somethings like Frame:Delete ?

thanks for any replies
  Reply With Quote
10-28-09, 08:54 PM   #2
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
No, this is not possible. Nor is it possible to give them to the Lua garbage collection facility. What you need to do is create these things once and re-use them as they're needed.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
10-29-09, 04:25 AM   #3
richardCANE
A Murloc Raider
Join Date: Oct 2009
Posts: 5
thanks for reply

and how to do that? can you give me some little example in LUA? how can i reuse the elements?
  Reply With Quote
10-29-09, 04:32 AM   #4
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
lua Code:
  1. local framepool = {}
  2.  
  3. local function removeframe(f)
  4.     f:Hide()
  5.     tinsert(framepool, f)
  6. end
  7.  
  8. local function getframe()
  9.     local f = tremove(framepool)
  10.     if not f then
  11.         --Create your frame here and assign it to f
  12.     else
  13.         --revert any unique changes you may have made to the frame before sticking it in the framepool
  14.     end
  15.     return f
  16. end

Something like that as a very basic example
  Reply With Quote
10-29-09, 04:59 AM   #5
richardCANE
A Murloc Raider
Join Date: Oct 2009
Posts: 5
thank you so much
  Reply With Quote
11-23-09, 01:32 PM   #6
maximdewit
A Murloc Raider
 
maximdewit's Avatar
Join Date: Nov 2009
Posts: 4
cant you for example simply write frame=nil?

dont shoot me ^^

--
  Reply With Quote
11-23-09, 01:33 PM   #7
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,609
That nils the reference to the frame, and maybe its properties, but the actual frame object is still in memory.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
11-23-09, 06:59 PM   #8
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
Originally Posted by maximdewit View Post
cant you for example simply write frame=nil?

dont shoot me ^^

--
I have to shoot you. Four posts above yours, I explained that this wasn't possible.

*BLAM!*
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
11-23-09, 10:01 PM   #9
ChaosInc
Curse staff
 
ChaosInc's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 672
But you can reduce the memory allocation by stripping the variable of it's data with f={}.
  Reply With Quote
11-23-09, 10:11 PM   #10
Akryn
A Firelord
AddOn Author - Click to view addons
Join Date: Mar 2008
Posts: 479
Originally Posted by ChaosInc View Post
But you can reduce the memory allocation by stripping the variable of it's data with f={}.
That's still just re-pointing the pointer, it's not even as good as f=nil.
  Reply With Quote
11-24-09, 12:17 AM   #11
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
And what about table.wipe(f) ?
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
11-24-09, 12:20 AM   #12
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
That does nothing for frames but clear their table members. The frame itself still exists, and will always exist until the UI is reloaded or you re-start WoW. Tables CAN be garbage-collected. Frames, though they are a special form of table, CANNOT.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
11-24-09, 03:08 AM   #13
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by Torhal View Post
That does nothing for frames but clear their table members. The frame itself still exists, and will always exist until the UI is reloaded or you re-start WoW. Tables CAN be garbage-collected. Frames, though they are a special form of table, CANNOT.
So basicly the closest you can get is like this:
lua Code:
  1. local function deleteframe(f)
  2.     if not f.DeletedEvent then
  3.         f.DeletedEvent = f.OnEvent
  4.         f:Hide()
  5.         f.OnEvent = function() end
  6.     end
  7. end
  8.  
  9. local function restoreframe(f)
  10.     if f.DeletedEvent then
  11.         f:Show()
  12.         f.OnEvent = f.DeletedEvent
  13.         f.DeletedEvent  = nil
  14.     end
  15. end
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
11-24-09, 03:45 PM   #14
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
No - that requires that you have a frame pointer for restoreframe(), which at that point isn't really possible without breaking the illusion that the frame has been "deleted". You would use this, instead:

Code:
local AcquireFrame, ReleaseFrame
do
	local frame_cache = {}

	function AcquireFrame(parent)
		local frame = tremove(frame_cache) or CreateFrame("Frame")
		frame:SetParent(parent)
		return frame
	end

	function ReleaseFrame(frame)
		frame:Hide()
		frame:SetParent(nil)
		frame:ClearAllPoints()
		tinsert(frame_cache, frame)
	end
end	-- do block
I also don't see the purpose in replacing the frame's OnEvent script - perhaps you're thinking of OnUpdate...but that never fires when the frame is hidden anyway.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.

Last edited by Torhal : 11-24-09 at 03:48 PM.
  Reply With Quote
11-25-09, 12:22 AM   #15
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by Torhal View Post
No - that requires that you have a frame pointer for restoreframe(), which at that point isn't really possible without breaking the illusion that the frame has been "deleted". You would use this, instead:

Code:
local AcquireFrame, ReleaseFrame
do
	local frame_cache = {}

	function AcquireFrame(parent)
		local frame = tremove(frame_cache) or CreateFrame("Frame")
		frame:SetParent(parent)
		return frame
	end

	function ReleaseFrame(frame)
		frame:Hide()
		frame:SetParent(nil)
		frame:ClearAllPoints()
		tinsert(frame_cache, frame)
	end
end	-- do block
I also don't see the purpose in replacing the frame's OnEvent script - perhaps you're thinking of OnUpdate...but that never fires when the frame is hidden anyway.
Because it might be - for example - registered to PLAYER_REGEN_DISABLED and in the event handler it shows itself, and sets it to a certain point for example? And something is wrong with your frame_cache table, it works fine as long as you work with 1 frame, but with multiple frames you would get the wrong one back from the acquire function.
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
11-25-09, 05:11 AM   #16
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
Originally Posted by nightcracker View Post
Because it might be - for example - registered to PLAYER_REGEN_DISABLED and in the event handler it shows itself, and sets it to a certain point for example? And something is wrong with your frame_cache table, it works fine as long as you work with 1 frame, but with multiple frames you would get the wrong one back from the acquire function.
There is nothing wrong with the code. We were talking about deleting a Frame, which we established was impossible to do.

This code gives you a way to say "I no longer need this frame. Make it go away." while still giving you a way to re-claim it later if it's needed, or a create a new one if there are none currently in the cache. If you want to be sure you're dealing with the same frame every time, why in the hell would you "delete" it and then "reclaim" it? Just hide the damn thing and unregister its events, then un-hide it when you need it to be available again. Also, setting an OnEvent script like this:

Code:
        frame:SetScript("OnEvent", function() end)
...creates an empty function which uses memory that must be dealt with later by the garbage collector when it's no longer being referenced whereas simply calling

Code:
        frame:UnregisterEvent(PLAYER_REGEN_DISABLED)
or even (though, again, WHY?)

Code:
        frame:SetScript("OnEvent", nil)
are both "free" methods and do what you need without pretending that you're deleting a frame which you obviously aren't because you have to have a handle to it to "undelete" it. Always remember: There is no such thing as a magic bullet - things which appear to be usually have hidden caveats.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.

Last edited by Torhal : 11-25-09 at 05:16 AM.
  Reply With Quote
11-25-09, 12:01 PM   #17
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
I see, but still I think you should clean up the frame a little bit more, since once you'd want to reuse a frame you get all the rubbish hooked to it. What about this? I'm planning to release it as a lib.
LUA Code:
  1. FrameHandler = {
  2.     cache = {},
  3.     scripts = {
  4.         OnDragStart = true,
  5.         OnDragStop = true,
  6.         OnEnter = true,
  7.         OnEvent = true,
  8.         OnKeyDown = true,
  9.         OnKeyUp = true,
  10.         OnLeave = true,
  11.         OnLoad = true,
  12.         OnMouseDown = true,
  13.         OnMouseUp = true,
  14.         OnMouseWheel = true,
  15.         OnReceiveDrag = true,
  16.         OnSizeChanged = true,
  17.         OnUpdate = true,
  18.     },
  19. }
  20.  
  21. function FrameHandler:CreateFrame(parent, name, inherits)
  22.     local parent = parent or UIParent
  23.     local f = tremove(FrameHandler.cache) or CreateFrame("Frame")
  24.     if name or inherits then
  25.         local f = CreateFrame("Frame", name, parent, inherits)
  26.     else
  27.         local f = tremove(FrameHandler.cache) or CreateFrame("Frame")
  28.     end
  29.     f:SetParent(parent)
  30.     f:Show()
  31.     return f
  32. end
  33.  
  34. function FrameHandler:DeleteFrame(f)
  35.     local name = f:GetName()
  36.     f:Hide()
  37.     f:SetParent(nil)
  38.     f:UnregisterAllEvents()
  39.     f:SetID(0)
  40.     f:ClearAllPoints()
  41.     for script, _ in pairs(FrameHandler.scripts) do
  42.         f:SetScript(script, nil)
  43.     end
  44.     if name then
  45.         _G[name] = nil
  46.     end
  47.     tinsert(FrameHandler.cache, f)
  48. end
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
11-25-09, 02:58 PM   #18
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
I do not see any benefit in having this exist as a library - the caching code is simple and small enough to be included directly within the AddOn. Also, indiscriminately setting all scripts to nil and removing the global name can cause an assortment of issues. If you're making a named frame, or setting scripts to it, you're generally going to want to keep it around so removing either makes no sense. Also, you cannot determine the intent of such a library's users - they may want the ability to safely add and remove frames for a frame factory, but not do all of the things you are doing.

The code I pasted here is ripped from my own LibQTip library, which manages its OWN frames since it knows all the attributes which are set on them. A general-purpose library that attempts to do such a thing will ultimately fail. AddOn A does this:

Code:
frame.this_is_awesome = function(self, arg1) DoStuff() end
and then releases the frame to the general-purpose frame-recycling library. AddOn B grabs that frame from the lib's cache, does other stuff to it, and shoves it back when done. After all of this modification and passing around, the frames will end up using more memory overall than a discrete AddOn-specific cache would ever dream of, since it has absolutely no knowledge of what the AddOns that use it are doing to the frames and therefore has no way to properly clean them up.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.

Last edited by Torhal : 11-25-09 at 03:05 PM.
  Reply With Quote
11-25-09, 03:54 PM   #19
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Originally Posted by Torhal View Post
I do not see any benefit in having this exist as a library - the caching code is simple and small enough to be included directly within the AddOn. Also, indiscriminately setting all scripts to nil and removing the global name can cause an assortment of issues. If you're making a named frame, or setting scripts to it, you're generally going to want to keep it around so removing either makes no sense. Also, you cannot determine the intent of such a library's users - they may want the ability to safely add and remove frames for a frame factory, but not do all of the things you are doing.

The code I pasted here is ripped from my own LibQTip library, which manages its OWN frames since it knows all the attributes which are set on them. A general-purpose library that attempts to do such a thing will ultimately fail. AddOn A does this:

Code:
frame.this_is_awesome = function(self, arg1) DoStuff() end
and then releases the frame to the general-purpose frame-recycling library. AddOn B grabs that frame from the lib's cache, does other stuff to it, and shoves it back when done. After all of this modification and passing around, the frames will end up using more memory overall than a discrete AddOn-specific cache would ever dream of, since it has absolutely no knowledge of what the AddOns that use it are doing to the frames and therefore has no way to properly clean them up.
Your right (damn, sometimes that's really hard to say you know?)
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
11-25-09, 03:58 PM   #20
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
That's why remembering that there's no such thing as a magic bullet is so important.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Remove a Frame element with LUA

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