events.nim 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. {.deprecated: [TEventArgs: EventArgs, TEventHandler: EventHandler,
  43. TEventEmitter: EventEmitter, EInvalidEvent: EventError].}
  44. proc initEventHandler*(name: string): EventHandler =
  45. ## Initializes an EventHandler with the specified name and returns it.
  46. result.handlers = @[]
  47. result.name = name
  48. proc addHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}) =
  49. ## Adds the callback to the specified event handler.
  50. handler.handlers.add(fn)
  51. proc removeHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}) =
  52. ## Removes the callback from the specified event handler.
  53. for i in countup(0, len(handler.handlers)-1):
  54. if fn == handler.handlers[i]:
  55. handler.handlers.del(i)
  56. break
  57. proc containsHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}): bool =
  58. ## Checks if a callback is registered to this event handler.
  59. return handler.handlers.contains(fn)
  60. proc clearHandlers*(handler: var EventHandler) =
  61. ## Clears all of the callbacks from the event handler.
  62. setLen(handler.handlers, 0)
  63. proc getEventHandler(emitter: var EventEmitter, event: string): int =
  64. for k in 0..high(emitter.s):
  65. if emitter.s[k].name == event: return k
  66. return -1
  67. proc on*(emitter: var EventEmitter, event: string, fn: proc(e: EventArgs) {.closure.}) =
  68. ## Assigns a event handler with the specified callback. If the event
  69. ## doesn't exist, it will be created.
  70. var i = getEventHandler(emitter, event)
  71. if i < 0:
  72. var eh = initEventHandler(event)
  73. addHandler(eh, fn)
  74. emitter.s.add(eh)
  75. else:
  76. addHandler(emitter.s[i], fn)
  77. proc emit*(emitter: var EventEmitter, eventhandler: var EventHandler,
  78. args: EventArgs) =
  79. ## Fires an event handler with specified event arguments.
  80. for fn in items(eventhandler.handlers): fn(args)
  81. proc emit*(emitter: var EventEmitter, event: string, args: EventArgs) =
  82. ## Fires an event handler with specified event arguments.
  83. var i = getEventHandler(emitter, event)
  84. if i >= 0:
  85. emit(emitter, emitter.s[i], args)
  86. proc initEventEmitter*(): EventEmitter =
  87. ## Creates and returns a new EventEmitter.
  88. result.s = @[]