Introduction
EScala can be used as a standard Scala library. This section shows examples on how to use the library with an unmodified version of the language. A complete example is available for download in the Download section.
The event library classes are all in the events.lib
package.
Event declaration
All the event are a subtype of events.lib.Event[T]
.
Events are declared as values
import events.lib._
class Figure {
lazy val changed = new ImperativeEvent[Unit]
}
This declares an imperative event which takes Unit
as parameter, i.e. no parameter. This event can be explicitly triggered in the code as a method call.
val f = new Figure
// trigger the changed event
f.changed()
Events can also be combined together using the combinator methods available in the Event
trait
class Figure {
// event emitting two integers
lazy val figureMoved = new ImperativeEvent[(Int, Int)]
// event emitting an integer
lazy val colorChanged = new ImperativeEvent[Int]
// disjunction of both previously declared events
// parameters are dropped to unify the event types
lazy val changed: Event[Unit] = figureMoved.dropParam || colorChanged.dropParam
}
Some of the available combinators are
- Events disjunction
e1 || e2
Both event types must be compatible. - Events conjunction
e1 && e2
Event types are merged to a pair. - Event filter
e && predicate
predicate
is a method returning a boolean. The resulting event matches only if teh event was triggered and the predicate was true. - Parameter mapping
e.map(transformation)
It allows to map the value provided by the event to an other type or value. The resulting event parameter has for type the return type of thetransformation
method - Parameter droping
e.dropParam
Equivalent to themap
operator with atransformation
method doing nothing and returningUnit
Reactions registration
Reactions can be registered to an event by using the +=
operator
class Figure {
…
def reaction() {
// react to the event
}
changed += reaction
The reaction must take as parameter the value provided by the observed event.
It is also possible to deregister a reaction using the -=
operator. In this case the reaction method must be declared as lazy value.
class Figure {
…
lazy val reaction = () => {
// do something
}
changed += reaction
def undeploy {
changed -= reaction
}
}
Variable references
The library provides two utility classes allowing to reference events of mutable variables
Variable[T]
wraps a variable of typeT
. It notifies the changes of the reference through achanged
event. It also provides anevent
operator which takes a function computing an event from the wrapped object as parameter and returns the event depending on the object.VarList[T]
is an observable list. It provides a methodany
which aggregates the events of the elements in the list, described by a function passed as parameter. The list observes changes in its content, which allows to aggregate the events of its current elements.
Observable methods
Implicit events can be observed by lifting a method to make it observable
class Figure {
lazy val moveBy = Observable((dx: Int, dy: Int) => {
// move the figure
})
}
Such a lifted methods exposes then two implicit events named before
and after
which are triggered before reps. after the method call. They can be used to declare more complex events.
class Figure {
lazy val figureMoved: Event[(Int, Int)]= moveBy.after
}
Implicit conversions
The event library contains an object named EventsLibConversions
providing useful implicit conversions. Among others it provides following conversion
- Wrapping an object of type
T
into an object of typeVariable[T]
- Converting a
Function1[T,R]
object to a correspondingObservable[T,R]
object - Converting a
FunctionN
object to the corresponding tupled function or aFunction0[R]
object to the correspondingFunction1[Unit, R]
object.