PublisherListener.scala 2.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package de.tu_darmstadt.cs.esa.tapasco.util
import  scala.collection.mutable.ArrayBuffer
import  scala.language.implicitConversions

/** Listener receives events of type A from a [[Publisher]]. */
trait Listener[A] {
  /** Called by publishers, where this Listener was registered. */
  def update(e: A): Unit
}

/** A Publisher broadcasts events of abstract type [[Publisher.Event]].
 *  [[Listener]] instances can register via its public registrations methods
 *  [[+=]], [[addListener]], [[-=]] and [[remListener]].
 *
 *  '''Example''':
 *  {{{
 *  // define the Publisher
 *  object Something extends Publisher {
 *    // Event type definition
 *    sealed trait Event
 *    // Event instances
 *    final case object ItHappened extends Event
 *    final case object ItHappenedAgain extends Event
 *
 *    ...
 *
 *    def update() {
 *      // publish events
 *      publish(ItHappened)
 *      publish(ItHappenedAgain)
 *    }
 *  }
 *
 *  ...
 *  // later register a Listener:
 *  Something += new Listener[Something.Event] {
 *    // will be called upon publish
 *    def update(e: Event) {
 *      ...
 *    }
 *  }
 *  }}}
 **/
trait Publisher {
  /** Type of events published by this Publisher. */
  type Event

  /** Type alias for listeners. */
  type EventListener = Listener[Event]

Jens Korinth's avatar
Jens Korinth committed
51
  /** Internal array of listeners. */
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  protected val _listeners: ArrayBuffer[EventListener] = new ArrayBuffer()

  /** Adds an [[EventListener]].
   *  @param el [[EventListener]] instance to register.
   *  @see [[+=]]
   */
  def addListener(el: EventListener) { this += el }

  /** Adds an [[EventListener]].
   *  @param el [[EventListener]] instance to register.
   *  @see [[addListener]]
   */
  def +=(el: EventListener) { _listeners.synchronized { _listeners += el } }

  /** Removes an [[EventListener]].
   *  @param el [[EventListener]] instance to deregister.
   *  @see [[-=]]
   */
  def remListener(el: EventListener) { this -= el }

  /** Removes an [[EventListener]].
   *  @param el [[EventListener]] instance to deregister.
   *  @see [[-=]]
   */
  def -=(el: EventListener): Unit = _listeners.synchronized { _listeners -= el }

  /** Publishes the given event.
   *  @param e [[Event]] to publish.
   **/
  def publish(e: Event) { _listeners.synchronized { _listeners.toSeq } foreach (_.update(e)) }
}

/** Companion object to [[Publisher]]. */
object Publisher {
  /** Implicitly converts a [[Publisher]] to a sequence of its [[Publisher.EventListener]]s.
   *  @note Thread-safe, will return immutable copy.
   */
  implicit def toListenerSeq(p: Publisher): Seq[p.EventListener] =
    p._listeners.synchronized { p._listeners.toSeq }
}