MattiasBuelens

Common observable

Jul 5th, 2012
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 2.35 KB | None | 0 0
  1. --[[
  2.  
  3.     Common utilities
  4.     Observable
  5.  
  6. --]]
  7.  
  8. common = common or {}
  9.  
  10. local Observable = common.newClass{
  11.     events = nil
  12. }
  13. common.Observable = Observable
  14.  
  15. local Event = common.newClass{
  16.     handlers = nil
  17. }
  18.  
  19. local Handler = common.newClass{
  20.     func = nil,
  21.     ctxt = nil,
  22.     prio = nil,
  23.  
  24.     -- Compare by members
  25.     __eq = function(h1, h2)
  26.         return h1.func == h2.func
  27.             and h1.ctxt == h2.ctxt
  28.             and h1.prio == h2.prio
  29.     end
  30. }
  31.  
  32. function Handler.compareByPriority(a, b)
  33.     return a.prio < b.prio
  34. end
  35.  
  36. function Observable:init()
  37.     self.events = self.events or {}
  38. end
  39.  
  40. function Observable:on(event, ...)
  41.     local e = self.events[event] or Event:new()
  42.     self.events[event] = e
  43.  
  44.     return e:add(...)
  45. end
  46.  
  47. function Observable:off(event, ...)
  48.     local e = self.events[event]
  49.     return e == nil or e:remove(...)
  50. end
  51.  
  52. function Observable:trigger(event, ...)
  53.     local e = self.events[event]
  54.     return e == nil or e:trigger(...)
  55. end
  56.  
  57. function Event:init()
  58.     self.handlers = self.handlers or {}
  59. end
  60.  
  61. function Event:add(func, ctxt, prio)
  62.     assert(type(func) == "function", "invalid handler")
  63.     if type(ctxt) ~= "table" then
  64.         ctxt = nil
  65.     end
  66.     if type(prio) ~= "number" then
  67.         prio = 0
  68.     end
  69.  
  70.     if self:find(func, ctxt, prio) ~= nil then
  71.         return true
  72.     end
  73.  
  74.     local handler = Handler:new{
  75.         func = func,
  76.         ctxt = ctxt,
  77.         prio = prio
  78.     }
  79.  
  80.     table.insert(self.handlers, handler)
  81.  
  82.     -- Sort by priority
  83.     table.sort(self.handlers, Handler.compareByPriority)
  84.     return true
  85. end
  86.  
  87. function Event:remove(func, ctxt, prio)
  88.     assert(type(func) == "function", "invalid handler")
  89.     if type(ctxt) ~= "table" then
  90.         ctxt = nil
  91.     end
  92.     if type(prio) ~= "number" then
  93.         prio = 0
  94.     end
  95.  
  96.     local i = self:find(func, ctxt, prio)
  97.  
  98.     if i == nil then
  99.         return false
  100.     end
  101.  
  102.     table.remove(self.handlers, i)
  103.     return true
  104. end
  105.  
  106. function Event:trigger(...)
  107.     local result = nil
  108.  
  109.     for i,handler in ipairs(self.handlers) do
  110.         if handler.ctxt == nil then
  111.             -- Call without context
  112.             result = handler.func(...) or result
  113.         else
  114.             -- Call with context
  115.             result = handler.func(handler.ctxt, ...) or result
  116.         end
  117.     end
  118.  
  119.     return result
  120. end
  121.  
  122. function Event:find(func, ctxt, prio)
  123.     -- Handler to find
  124.     local handler = Handler:new{
  125.         func = func,
  126.         ctxt = ctxt,
  127.         prio = prio
  128.     }
  129.  
  130.     for i,v in ipairs(self.handlers) do
  131.         if v == handler then
  132.             return i
  133.         end
  134.     end
  135.  
  136.     return nil
  137. end
Advertisement
Add Comment
Please, Sign In to add comment