events.nim 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2011 Alexander Mitchell-Robinson
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## :Author: Alexander Mitchell-Robinson (Amrykid)
  10. ##
  11. ## This module implements an event system that is not dependent on external
  12. ## graphical toolkits. It was originally called ``NimEE`` because
  13. ## it was inspired by Python's PyEE module. There are two ways you can use
  14. ## events: one is a python-inspired way; the other is more of a C-style way.
  15. ##
  16. ## .. code-block:: Nim
  17. ## var ee = initEventEmitter()
  18. ## var genericargs: EventArgs
  19. ## proc handleevent(e: EventArgs) =
  20. ## echo("Handled!")
  21. ##
  22. ## # Python way
  23. ## ee.on("EventName", handleevent)
  24. ## ee.emit("EventName", genericargs)
  25. ##
  26. ## # C/Java way
  27. ## # Declare a type
  28. ## type
  29. ## SomeObject = object of RootObj
  30. ## SomeEvent: EventHandler
  31. ## var myobj: SomeObject
  32. ## myobj.SomeEvent = initEventHandler("SomeEvent")
  33. ## myobj.SomeEvent.addHandler(handleevent)
  34. ## ee.emit(myobj.SomeEvent, genericargs)
  35. type
  36. EventArgs* = object of RootObj ## Base object for event arguments that are passed to callback functions.
  37. EventHandler* = tuple[name: string, handlers: seq[proc(e: EventArgs) {.closure.}]] ## An eventhandler for an event.
  38. type
  39. EventEmitter* = object ## An object that fires events and holds event handlers for an object.
  40. s: seq[EventHandler]
  41. EventError* = object of ValueError
  42. proc initEventHandler*(name: string): EventHandler =
  43. ## Initializes an EventHandler with the specified name and returns it.
  44. result.handlers = @[]
  45. result.name = name
  46. proc addHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}) =
  47. ## Adds the callback to the specified event handler.
  48. handler.handlers.add(fn)
  49. proc removeHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}) =
  50. ## Removes the callback from the specified event handler.
  51. for i in countup(0, len(handler.handlers)-1):
  52. if fn == handler.handlers[i]:
  53. handler.handlers.del(i)
  54. break
  55. proc containsHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}): bool =
  56. ## Checks if a callback is registered to this event handler.
  57. return handler.handlers.contains(fn)
  58. proc clearHandlers*(handler: var EventHandler) =
  59. ## Clears all of the callbacks from the event handler.
  60. setLen(handler.handlers, 0)
  61. proc getEventHandler(emitter: var EventEmitter, event: string): int =
  62. for k in 0..high(emitter.s):
  63. if emitter.s[k].name == event: return k
  64. return -1
  65. proc on*(emitter: var EventEmitter, event: string, fn: proc(e: EventArgs) {.closure.}) =
  66. ## Assigns a event handler with the specified callback. If the event
  67. ## doesn't exist, it will be created.
  68. var i = getEventHandler(emitter, event)
  69. if i < 0:
  70. var eh = initEventHandler(event)
  71. addHandler(eh, fn)
  72. emitter.s.add(eh)
  73. else:
  74. addHandler(emitter.s[i], fn)
  75. proc emit*(emitter: var EventEmitter, eventhandler: var EventHandler,
  76. args: EventArgs) =
  77. ## Fires an event handler with specified event arguments.
  78. for fn in items(eventhandler.handlers): fn(args)
  79. proc emit*(emitter: var EventEmitter, event: string, args: EventArgs) =
  80. ## Fires an event handler with specified event arguments.
  81. var i = getEventHandler(emitter, event)
  82. if i >= 0:
  83. emit(emitter, emitter.s[i], args)
  84. proc initEventEmitter*(): EventEmitter =
  85. ## Creates and returns a new EventEmitter.
  86. result.s = @[]