-
Posted by Myrroddin on Tue, 07 Feb 2012 10:28:46
I am trying to replicate AceEvent-3.0's UnregisterEvent and UnregisterAllEvents using table.remove, as Rift uses table.insert to register events. There is a great deal of information provided here, but thus far haven't had any responses.
The short of it is I would like to create a library file that introduces those two APIs, but I'm not sure how to use table.remove correctly in this case. For the first one, I am thinking it might be something like
function lib:UnregisterEvent(Event, Identifier) if type(Event) ~= "table" then error("The event %s is not a table", Utility.Serialize.Inline(Event), 2) elseif type(Identifier) ~= "string" then error("The Identifier %s is not a string", Identifier, 2) end for i, value in pairs(Event[Identifier]) do value[i] = nil end end
I am not quite certain where to use Utility.Dispatch, and while I am not certain if the above will work, I definitely don't know what I am doing to create UnregisterAllEvents specifically for one Identifier (or addon).
Any suggestions welcome.
Also, I just want to thank you (again) for the books, the site, and all your help and documentation. Over in WoW, without your help, I never would have got SmartRes2 up and running.
-
Posted by Myrroddin on Tue, 07 Feb 2012 10:47:15
With Utility.Dispatch, I think the first one might look like
function lib:UnregisterEvent(Event, Identifier, [func, funcDesc]) -- func is optional if type(Event) ~= "table" then error("The event %s is not a table", Utility.Serialize.Inline(Event), 2) elseif type(Identifier) ~= "string" then error("The Identifier %s is not a string", Identifier, 2) end for i, value in pairs(Event[Identifier]) do value[i] = nil end if func then if type(func) ~= "function" then error("The function %s not a function", func, 2) elseif type(funcDesc) ~= "string" then error("Function description %s is not a string", funcDesc, 2) end Utility.Dispatch(func, Identifier, funcDesc) end end
-
Posted by jnwhiteh on Tue, 07 Feb 2012 11:51:02
It depends entirely on how event registration is done behind the scenes. The following might show you how to register and then unregister a single event.
-- Register an event local eventTbl = {function, "Identifier", "function description string"} table.insert(Event.Name, eventTbl) -- Unregister that event for idx, eventData in ipairs(Event.Name) do if eventData == eventTbl then table.remove(Event.Name, idx) break end end
So perhaps something like this:
-- Removes all event registrations in eventName with the given identifier function lib:UnregisterEvent(eventName, identifier) local i = 1 while i < len(eventName) do local data = eventName[i] if data[2] == identifier then table.remove(eventName, i) else i = i + 1 end end end
-
Posted by Myrroddin on Tue, 07 Feb 2012 16:25:41
Hmm, interesting. I was doing some more thinking, and here is my modified and updated pastebin. The problem that is making me seek help is that not everybody breaks up the table.insert into two pieces. Most authors are simply doing
table.insert(Event.Some.Thing, {function, "Identifier", "func string"})
Therefore simply removing elements doesn't seem likely. The result is the same, but the implemtation is different. The second issue is that all events are named Event.Some.Thing, Event.Some.Other, etc, when trying to remove all events, I am looking for a way to match a string"Event.*"
without knowing what the".*"
could be. And that brings up matching a table name with a string, which is another bag of tricks I haven't mastered.It wouldn't do to simply match all the
Event.*
stuff for all addons; as your code pointed out, it would have to be specifically targeting an identifier.I get why Trion is using tables, besides being different; it makes adding new return values to them, or deleting obsolete entries, very easy on their end. Same thing with their Inspectors, which is their version of WoW's GetSomeData. A table again. On the other hand, it also creates a need for this library because they either can't, or won't, build in the functionality.
-
Posted by jnwhiteh on Tue, 07 Feb 2012 16:34:13
What about something like this. I'm not sure why there was a problem with anything I posted before, I'm not sure of your complaint/concern.
-- Remove all entries for 'Identifier' from all events under this one. For -- example, if you call UnregisterForAllIdentifier(Event.Foo, "Blah") and -- there are events Event.Foo.Bar and Event.Foo.Bar.Baz, then this will remove -- any registrations for "Blah" from all of those events. function UnregisterAllForIdentifier(event, identifier) -- First remove any event registrations with this identifier from this -- level (i.e. from Event first). This code can be much easier if you can -- guarantee that each Identifier will only be registered for a given -- event exactly once. local idx = 1 while idx < #event do local data = event[idx] if data[2] == identifier then -- check if the identifier matches table.remove(event, idx) else idx = idx + 1 end end for key, value in pairs(event) do if type(key) == "string" then -- This should be "Foo" from event.Foo, so we want to recurse UnregisterAllForIdentifier(value, identifier) end end end
-
Posted by Myrroddin on Tue, 07 Feb 2012 16:50:16
What about something like this. I'm not sure why there was a problem with anything I posted before, I'm not sure of your complaint/concern.
I didn't have a complaint or concern, sorry about the confusion. I had just posted my pastebin at the same time you had answered. A crossing in the interwebs, as it were.
The code you just posted is the equivalent for UnregisterAllEvents(identifier), yes? How does my code for UnregisterSingleEvent stack up? I will try your code and let a few other authors give it a whirl.
-
Posted by jnwhiteh on Tue, 07 Feb 2012 16:54:08
What about something like this. I'm not sure why there was a problem with anything I posted before, I'm not sure of your complaint/concern.
I didn't have a complaint or concern, sorry about the confusion. I had just posted my pastebin at the same time you had answered. A crossing in the interwebs, as it were.
The code you just posted is the equivalent for UnregisterAllEvents(identifier), yes?
Only if you call it like MyLongFunctionName(Event, "Identifier"). You can wrap it however you want, but it just vacuously takes a table and scrubs all registrations for "Identifier" from that event, and all subevents.
How does my code for UnregisterSingleEvent stack up? I will try your code and let a few other authors give it a whirl.
Get rid of the recursion (the second loop) and that will unregister all registrations for the given identifier from the given event, again, called MyLongFunctionName(Event, "Identifier").
So to unregister "Foo" from Event.Unit.Health you'd do:
MyLongFuncName(Event.Unit.Health, "Foo")
You can even make the recursive part of it a parameter as well, to simplify your code and allow more re-use.
-
Posted by Myrroddin on Tue, 07 Feb 2012 17:20:01
I think I get it, hopefully. The end results would be two functions in the lib (I added the key = function, since you'd want to get rid of those too).
-- Remove all entries for 'Identifier' from all events under this one. For -- example, if you call UnregisterForAllIdentifier(Event.Foo, "Blah") and -- there are events Event.Foo.Bar and Event.Foo.Bar.Baz, then this will remove -- any registrations for "Blah" from all of those events. function UnregisterAllForIdentifier(event, identifier) -- First remove any event registrations with this identifier from this -- level (i.e. from Event first). This code can be much easier if you can -- guarantee that each Identifier will only be registered for a given -- event exactly once. local idx = 1 while idx < #event do local data = event[idx] if data[2] == identifier then -- check if the identifier matches table.remove(event, idx) else idx = idx + 1 end end for key, value in pairs(event) do if type(key) == "string" or type(key) == "function" then -- This should be "Foo" from event.Foo, so we want to recurse UnregisterAllForIdentifier(value, identifier) end end end function UnregisterSingleEventForIdentifier(identifier) for key, value in pairs(event) do if type(key) == "string" or type(key) == "function" then -- This should be "Foo" from event.Foo, so we want to recurse UnregisterAllForIdentifier(value, identifier) end end end
The next two would be called in MyAddon.lua, depending on what you wanted.
lib:UnregisterSingleEventForIdentifier(identifier) lib:UnregisterAllForIdentifier(event, identifier)
-
Posted by Myrroddin on Tue, 07 Feb 2012 17:24:02
Oh yes, you mentioned about each identifier being registered once per event: that is fair to assume, as you wouldn't register for the same event multiple times in the same addon, but different addons might register for the same event. Kind of like PerfectRaid and Pitbull both register for UnitHealth, but neither registers for UnitHealth more than once.