03/06/14, 11:02 PM | #1 | |
Join Date: Mar 2014
Posts: 16
|
Window Chaining
Looking through various add-ons, I've noticed that everyone seems to use a generic method chaining function.
I'd like to analyze this function and see if I understand what is happening. Any input/feedback that you guys can provide is much appreciated. The code I'm referring to is part of the "Crystal Fragments Passive" add-on by Lodur. Thanks to him! Here is the code Code:
function CFP.BallAndChain( object ) local T = {} setmetatable( T , { __index = function( self , func ) if func == "__BALL" then return object end return function( self , ... ) assert( object[func] , func .. " missing in object" ) object[func]( object , ... ) return self end end }) return T end Code:
CFP.TLW = CFP.BallAndChain( WINDOW_MANAGER:CreateTopLevelWindow("CFP_BuffDisplay") ) :SetHidden(true) :SetDimensions(w,h) .__BALL 1. We create a new TopLevelWindow (TLW for short) by calling WINDOW_MANAGER:CreateTopLevelWindow("CFP_BuffDisplay"). We pass this Window object to the method chaining function CFP.BallAndChain. 2. The BallAndChain function returns an empty table T...but defines this table's __index metamethod. 3. We attempt to call the SetHidden method on the returned empty table T. Written out explicitly, this would look like T.SetHidden(T, true). 4. Since SetHidden isn't defined in T...we look in the defined metatable for T and look for the __index metamethod. 5. The __index metamethod returns a function. The function returned will first check to see that the original attempted method (in this case SetHidden) is defined in the upvalue variable "object" which is the original TLW Window object. Assuming SetHidden is defined for this window object, SetHidden is executed on the object. Written out explicitly, this would look something like: Window.SetHidden(Window, true). Lastly, the "self" object is returned which is the TLW window object. NOTE: SetHidden doesn't even need to be defined for the Window object...so long as the Window object's __index metamethod eventually leads to the definition of SetHidden. 6. The same process as step 5 is executed for function SetDimensions with parameters w and h. 7. Simplifying, the entire call sort of looks like this: CFP.TLW = CFP.(hidden TLW object with set width and height).__BALL Since __BALL is not defined for this object, we again look at the defined __index metamethod. When the attempted function is __BALL, the Window object is finally returned to CFP.TLW. The final result here is we have created a TopLevelWindow object which has width = w, height = h, and is hidden from the user. Conclusion: It seems like the reason we need this function is because the original creation of the Window via WINDOW_MANAGER:CreateTopLevelWindow("CFP_BuffDisplay") would NOT work as part of a method chain. For example, if we tried to call WINDOW_MANAGER :CreateTopLevelWindow("CFP_BuffDisplay") :SetHidden(true) :SetDimensions(w,h) this would result in an error because WINDOW_MANAGER would be the object passed to each method in the chain, not the actual TLW object created. This is my analysis of what I think is happening. I look forward to you guys tearing this apart and telling me all the places where I am wrong . Thanks again and I look forward to learning more about this. Last edited by inDef : 03/06/14 at 11:32 PM. |
|
ESOUI » Developer Discussions » General Authoring Discussion » Window Chaining |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Switch to Linear Mode |
Switch to Hybrid Mode |
Threaded Mode |
|
|