-
Notifications
You must be signed in to change notification settings - Fork 3
/
events.go
107 lines (90 loc) · 2.69 KB
/
events.go
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
51
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package event
import "reflect"
// Handler allows callback registration and event fireing, its simply
// a way of comunication that comes handy in some cases, though is has
// performance cost, events are mapped to reflect.Type of an inputted
// anything, enum events are accessed by indexing into slice, if you
// don't have to pass arguments with event use Handler.Trigger and Handler.Run
// as it is cleaner and faster
type Handler struct {
callbacks map[reflect.Type][]func(interface{})
enumCallbacks [][]func()
}
// NHandler initializes inner map
func NHandler() *Handler {
return &Handler{
callbacks: map[reflect.Type][]func(interface{}){},
}
}
// Fire launches all event callbacks for given type
func (e *Handler) Fire(ev interface{}) {
for _, e := range e.callbacks[reflect.TypeOf(ev)] {
e(ev)
}
}
// On registers event callback
func (e *Handler) On(ev interface{}, f func(interface{})) {
e.callbacks[reflect.TypeOf(ev)] = append(e.callbacks[reflect.TypeOf(ev)], f)
}
// Trigger launches enum event callbacks
func (e *Handler) Trigger(en Enum) {
e.ensureLength(en)
for _, e := range e.enumCallbacks[en] {
e()
}
}
// Run register enum event callback
func (e *Handler) Run(en Enum, f func()) {
e.ensureLength(en)
e.enumCallbacks[en] = append(e.enumCallbacks[en], f)
}
// as we cannot know how match different EnEvents we have, its unreliable to hardcode a value
func (e *Handler) ensureLength(en Enum) {
for int(en) >= len(e.enumCallbacks) {
e.enumCallbacks = append(e.enumCallbacks, []func(){})
}
}
// Enum is to distinguish event enumeration
type Enum int
// String handles event registration for elements
type String map[string][]*Listener
// Add adds listener to handler, keep the listener accessable if you want to
// remove it later
func (e String) Add(listener *Listener) {
evs := e[listener.Name]
listener.idx = len(evs)
e[listener.Name] = append(evs, listener)
}
// Invoke invokes the event listeners, removed listeners are skipped and deleted
func (e String) Invoke(name string, ed interface{}) {
evs := e[name]
for i := len(evs) - 1; i >= 0; i-- {
evs[i].Runner(ed)
if evs[i].Block {
break
}
}
}
// Listener holds function tha gets called when event is triggered
// if events returns true, all consequent events will get blocked, execution
// goes from newest to oldest event listener
type Listener struct {
Name string
Block bool
Runner StringRunner
idx int
evs String
}
// Remove removes the listener from event handler
func (e *Listener) Remove() {
if e.evs == nil {
return
}
evs := e.evs[e.Name]
for i := e.idx; i < len(evs); i++ {
evs[i].idx--
}
evs = append(evs[:e.idx], evs[e.idx+1:]...)
e.evs[e.Name] = evs
}
type StringRunner func(i interface{})