window_blessing 0.0.1 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +30 -0
- data/README.md +1 -1
- data/bin/buffered_screen_demo.rb +4 -4
- data/bin/color_picker_demo.rb +1 -0
- data/bin/windowed_screen_demo.rb +1 -1
- data/bin/xterm_screen_demo.rb +6 -4
- data/lib/window_blessing.rb +2 -2
- data/lib/window_blessing/buffer.rb +16 -6
- data/lib/window_blessing/buffered_screen.rb +2 -2
- data/lib/window_blessing/color.rb +1 -0
- data/lib/window_blessing/debug_tools/log_request_redraw_internal.rb +16 -0
- data/lib/window_blessing/event_manager.rb +11 -6
- data/lib/window_blessing/evented.rb +1 -1
- data/lib/window_blessing/evented_variable.rb +10 -1
- data/lib/window_blessing/tools.rb +11 -1
- data/lib/window_blessing/version.rb +1 -1
- data/lib/window_blessing/widgets/draggable_background.rb +1 -1
- data/lib/window_blessing/widgets/label.rb +1 -1
- data/lib/window_blessing/widgets/slider.rb +10 -2
- data/lib/window_blessing/widgets/text_field.rb +1 -1
- data/lib/window_blessing/window.rb +48 -45
- data/lib/window_blessing/window_redraw_areas.rb +23 -0
- data/lib/window_blessing/windowed_screen.rb +11 -13
- data/lib/window_blessing/xterm_event_parser.rb +68 -59
- data/lib/window_blessing/xterm_screen.rb +2 -2
- data/lib/window_blessing/xterm_state.rb +1 -1
- data/spec/buffer_spec.rb +56 -0
- data/spec/color_spec.rb +14 -0
- data/spec/event_manager_spec.rb +107 -0
- data/spec/event_queue_spec.rb +46 -0
- data/spec/evented_variable_spec.rb +43 -0
- data/spec/tools_spec.rb +18 -0
- data/spec/window_redraw_areas_spec.rb +79 -0
- data/spec/window_spec.rb +138 -3
- data/spec/xterm_event_parser_spec.rb +86 -0
- data/window_blessing.gemspec +4 -3
- metadata +20 -11
- data/bin/foiled_demo.rb +0 -27
- data/bin/text_editor_demo.rb +0 -292
@@ -0,0 +1,23 @@
|
|
1
|
+
module WindowBlessing
|
2
|
+
class WindowRedrawAreas
|
3
|
+
include Tools
|
4
|
+
attr_reader :areas
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@areas = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# first pass merging algorithm:
|
11
|
+
# merge all overlapping areas with area until no overlapping areas
|
12
|
+
# This creates a non-overlapping set of areas, but it may be much bigger total area than before.
|
13
|
+
# TODO - for "two-point" overlaps - just shrink one of the rectangles so they don't overlap but still cover the same area
|
14
|
+
def <<(area)
|
15
|
+
overlapping, non_overlapping = @areas.partition {|a| a.overlaps?(area)}
|
16
|
+
while overlapping.length > 0
|
17
|
+
overlapping.each {|a| area &= a}
|
18
|
+
overlapping, non_overlapping = non_overlapping.partition {|a| a.overlaps?(area)}
|
19
|
+
end
|
20
|
+
@areas = non_overlapping + [area]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -20,32 +20,30 @@ class WindowedScreen < XtermScreen
|
|
20
20
|
@root_window.buffer.dirty
|
21
21
|
@root_window.name = "root_window"
|
22
22
|
|
23
|
-
event_manager.
|
24
|
-
if
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
buffer.clean
|
30
|
-
end
|
23
|
+
event_manager.on :tick do
|
24
|
+
if root_window.redraw_requested?
|
25
|
+
root_window.draw
|
26
|
+
buffer = root_window.buffer
|
27
|
+
output.draw_buffer buffer.dirty_area.loc, buffer.dirty_subbuffer if buffer.dirty_area
|
28
|
+
buffer.clean
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
|
-
event_manager.
|
32
|
+
event_manager.on :key_press do |event|
|
35
33
|
root_window.route_keyboard_event event
|
36
34
|
end
|
37
35
|
|
38
|
-
event_manager.
|
36
|
+
event_manager.on :string_input do |event|
|
39
37
|
root_window.route_keyboard_event event
|
40
38
|
end
|
41
39
|
|
42
|
-
event_manager.
|
40
|
+
event_manager.on :resize do |event|
|
43
41
|
root_window.size = event[:size]
|
44
42
|
root_window.request_redraw_internal
|
45
43
|
end
|
46
44
|
|
47
|
-
event_manager.
|
48
|
-
root_window.
|
45
|
+
event_manager.on :pointer do |event|
|
46
|
+
root_window.route_pointer_event event.clone
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -13,7 +13,7 @@ class XtermEventParser < BabelBridge::Parser
|
|
13
13
|
end
|
14
14
|
|
15
15
|
rule :event, /[^\x00-\x1f\x7F]+/ do
|
16
|
-
def event; {:
|
16
|
+
def event; {type: :string_input, string: to_s} end
|
17
17
|
end
|
18
18
|
|
19
19
|
rule :command, /[a-zA-Z]/
|
@@ -27,28 +27,27 @@ class XtermEventParser < BabelBridge::Parser
|
|
27
27
|
rule :event, "\e[8;", :numbers, "t" do
|
28
28
|
include GuiGeo
|
29
29
|
def event
|
30
|
-
{:
|
30
|
+
{type: :xterm_state, state_type: :size, state: point(*numbers.to_a.reverse)}
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
rule :event, "\e[4;", :numbers, "t" do
|
35
35
|
include GuiGeo
|
36
36
|
def event
|
37
|
-
{:
|
37
|
+
{type: :xterm_state, state_type: :display_pixel_size, state: point(*numbers.to_a.reverse)}
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
rule(:event, "\e\x7F") {def event;{:
|
42
|
-
rule(:event, "\x7F") {def event;{:
|
43
|
-
rule(:event, "\e[O") {def event;{:
|
44
|
-
rule(:event, "\e[I") {def event;{:
|
41
|
+
rule(:event, "\e\x7F") {def event;{type: [:key_press,:backspace], key: :backspace, alt:true };end}
|
42
|
+
rule(:event, "\x7F") {def event;{type: [:key_press,:backspace], key: :backspace};end}
|
43
|
+
rule(:event, "\e[O") {def event;{type: :blur};end}
|
44
|
+
rule(:event, "\e[I") {def event;{type: :focus};end}
|
45
45
|
|
46
46
|
rule :event, :key_press do
|
47
|
-
def event; {:
|
47
|
+
def event; {type: [:key_press,key], key: key}.merge(modifiers) end
|
48
48
|
|
49
49
|
def modifiers
|
50
|
-
|
51
|
-
m ? m.modifiers : []
|
50
|
+
key_press.modifier ? key_press.modifier.modifiers : {}
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
@@ -58,83 +57,89 @@ class XtermEventParser < BabelBridge::Parser
|
|
58
57
|
rule(:key_press, "\e", :modifier, "C") {def key;:right;end}
|
59
58
|
rule(:key_press, "\e", :modifier, "A") {def key;:up;end}
|
60
59
|
rule(:key_press, "\e", :modifier, "Z") {def key;:reverse_tab;end}
|
61
|
-
rule(:key_press, "\e", :modifier, "H") {def key;:home;end}
|
62
|
-
rule(:key_press, "\e", :modifier, "F") {def key;:end;end}
|
63
60
|
rule(:key_press, "\e", :modifier, "P") {def key;:f1;end}
|
64
61
|
rule(:key_press, "\e", :modifier, "Q") {def key;:f2;end}
|
65
62
|
rule(:key_press, "\e", :modifier, "R") {def key;:f3;end}
|
66
63
|
rule(:key_press, "\e", :modifier, "S") {def key;:f4;end}
|
67
|
-
rule(:key_press, "\e", :modifier, "F") {def key;:
|
68
|
-
rule(:key_press, "\e", :modifier, "H") {def key;:end;
|
64
|
+
rule(:key_press, "\e", :modifier, "F") {def key;:end;end;}
|
65
|
+
rule(:key_press, "\e", :modifier, "H") {def key;:home;end; }
|
69
66
|
|
70
67
|
rule :modifier, "\e", :modifier do
|
71
68
|
def modifiers
|
72
|
-
(modifier.modifiers ||
|
69
|
+
(modifier.modifiers || {}).merge alt:true
|
73
70
|
end
|
74
|
-
|
75
71
|
end
|
72
|
+
|
73
|
+
MODIFER_DECODER = {
|
74
|
+
2 => {shift: true},
|
75
|
+
3 => {alt: true},
|
76
|
+
4 => {shift: true, alt: true},
|
77
|
+
5 => {control: true},
|
78
|
+
6 => {shift: true, control: true},
|
79
|
+
7 => {alt: true, control: true},
|
80
|
+
8 => {shift: true, alt: true, control: true},
|
81
|
+
9 => {alt: true},
|
82
|
+
10 => {shift: true, alt: true},
|
83
|
+
}
|
84
|
+
|
76
85
|
rule :modifier, "[", :numbers do
|
77
86
|
def modifiers
|
78
|
-
{
|
79
|
-
2 => [:shift],
|
80
|
-
3 => [:alt],
|
81
|
-
4 => [:shift, :alt],
|
82
|
-
5 => [:control],
|
83
|
-
6 => [:shift, :control],
|
84
|
-
7 => [:alt, :control],
|
85
|
-
8 => [:shift, :alt, :control],
|
86
|
-
}[numbers.to_a[-1].to_i] || []
|
87
|
+
MODIFER_DECODER[numbers.to_a[-1].to_i] || {}
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
90
91
|
rule :modifier, /[\[O]/ do
|
91
|
-
def modifiers;
|
92
|
+
def modifiers; {}; end
|
92
93
|
end
|
93
94
|
|
94
|
-
|
95
|
+
KEY_MAP_DECODER = {
|
96
|
+
3 => :delete,
|
97
|
+
2 => :insert,
|
98
|
+
6 => :page_down,
|
99
|
+
5 => :page_up,
|
100
|
+
13 => :f3,
|
101
|
+
14 => :f4,
|
102
|
+
15 => :f5,
|
103
|
+
17 => :f6,
|
104
|
+
18 => :f7,
|
105
|
+
19 => :f8,
|
106
|
+
20 => :f9,
|
107
|
+
21 => :f10,
|
108
|
+
23 => :f11,
|
109
|
+
24 => :f12,
|
110
|
+
}
|
111
|
+
rule :event, "\e[", :number, match?(";2").as(:shift), "~" do
|
95
112
|
def event
|
113
|
+
key = KEY_MAP_DECODER[number.to_i]
|
96
114
|
{
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
2 => :insert,
|
101
|
-
6 => :page_down,
|
102
|
-
5 => :page_up,
|
103
|
-
13 => :f3,
|
104
|
-
14 => :f4,
|
105
|
-
15 => :f5,
|
106
|
-
17 => :f6,
|
107
|
-
18 => :f7,
|
108
|
-
19 => :f8,
|
109
|
-
20 => :f9,
|
110
|
-
21 => :f10,
|
111
|
-
23 => :f11,
|
112
|
-
24 => :f12,
|
113
|
-
}[number.to_i]
|
115
|
+
:type => [:key_press, key],
|
116
|
+
:key => key,
|
117
|
+
:shift => !!shift
|
114
118
|
}
|
115
119
|
end
|
116
120
|
end
|
117
121
|
|
122
|
+
BUTTON_ACTIONS = {
|
123
|
+
32 => [:button_down, 1], 33 => [:button_down, 2], 34=> [:button_down, 3], 35=>:button_up,
|
124
|
+
64 => :drag,
|
125
|
+
96 => :wheel_down, 97 => :wheel_up
|
126
|
+
}
|
127
|
+
|
118
128
|
rule :event, "\e[", "M", match(/.../).as(:state) do
|
129
|
+
include GuiGeo
|
119
130
|
def event
|
120
131
|
s, x, y = state.to_s.unpack "CCC"
|
121
132
|
x -= 33
|
122
133
|
y -= 33
|
123
|
-
button_actions = {
|
124
|
-
32 => :button1_down, 33 => :button2_down, 34=> :button3_down, 35=>:button_up,
|
125
|
-
64 => :drag,
|
126
|
-
96 => :wheel_down, 97 => :wheel_up
|
127
|
-
}
|
128
134
|
{
|
129
|
-
type:
|
130
|
-
button:
|
131
|
-
state:
|
132
|
-
loc:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
135
|
+
type: [:pointer, BUTTON_ACTIONS[s&99]].flatten,
|
136
|
+
button: BUTTON_ACTIONS[s&99],
|
137
|
+
state: s,
|
138
|
+
loc: point(x,y),
|
139
|
+
shift: (s&4)!=0,
|
140
|
+
alt: (s&8)!=0,
|
141
|
+
control: (s&16)!=0,
|
142
|
+
}
|
138
143
|
end
|
139
144
|
end
|
140
145
|
|
@@ -145,10 +150,14 @@ class XtermEventParser < BabelBridge::Parser
|
|
145
150
|
end
|
146
151
|
end
|
147
152
|
|
153
|
+
rule(:event, "\e") {def event; {type: [:key_press, :escape], :key=>:escape} end}
|
154
|
+
rule(:event, "\r") {def event; {type: [:key_press, :enter], :key=>:enter} end}
|
155
|
+
rule(:event, "\t") {def event; {type: [:key_press, :tab], :key=>:tab} end}
|
156
|
+
|
148
157
|
rule :event, /[\x00-\x1f]/ do
|
149
158
|
def event
|
150
159
|
char = "%c"%(to_s.getbyte(0)+"`".getbyte(0))
|
151
|
-
{:
|
160
|
+
{type: [:key_press, char.to_sym], key: char.to_sym, control: true}
|
152
161
|
end
|
153
162
|
end
|
154
163
|
|
@@ -14,8 +14,8 @@ class XtermScreen
|
|
14
14
|
@pending_events = []
|
15
15
|
@event_queue = EventQueue.new
|
16
16
|
|
17
|
-
@event_manager.
|
18
|
-
quit if event[:key]==:
|
17
|
+
@event_manager.on :key_press do |event|
|
18
|
+
quit if event[:control] && event[:key]==:q
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -5,7 +5,7 @@ class XtermState
|
|
5
5
|
def initialize(event_manager)
|
6
6
|
@state = {:size => point(-1,-1)}
|
7
7
|
|
8
|
-
event_manager.
|
8
|
+
event_manager.on :xterm_state do |event|
|
9
9
|
state_type = event[:state_type]
|
10
10
|
old_state = state[state_type]
|
11
11
|
new_state = event[:state]
|
data/spec/buffer_spec.rb
CHANGED
@@ -47,6 +47,12 @@ describe "Buffer" do
|
|
47
47
|
fb.to_s.should == "----\n----\n----\n----"
|
48
48
|
end
|
49
49
|
|
50
|
+
it "fill out of bounds" do
|
51
|
+
fb = buffer(point(4,4))
|
52
|
+
fb.fill :area => rect(0,-4,1,1), :string => "-", :bg=>color(0,0,0)
|
53
|
+
fb.to_s.should == " \n \n \n "
|
54
|
+
end
|
55
|
+
|
50
56
|
it "cropped fill" do
|
51
57
|
(f=test_frame).cropped(rect(1,1,2,1)) do
|
52
58
|
f.fill :string => '-'
|
@@ -166,5 +172,55 @@ describe "Buffer" do
|
|
166
172
|
f1.fg_buffer.should == [[7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7]]
|
167
173
|
f1.bg_buffer.should == [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
168
174
|
end
|
175
|
+
|
176
|
+
it "sanitize_contents" do
|
177
|
+
f1 = test_frame
|
178
|
+
f1.contents = "hi\t!\nthere"
|
179
|
+
f1.to_s.should == "hi?!\nther\n \n "
|
180
|
+
f1.contents[1]="boo\x00"
|
181
|
+
f1.to_s.should == "hi?!\nboo\x00\n \n "
|
182
|
+
f1.sanitize_contents 2..-1
|
183
|
+
f1.to_s.should == "hi?!\nboo\x00\n \n "
|
184
|
+
f1.sanitize_contents 1..1
|
185
|
+
f1.to_s.should == "hi?!\nboo?\n \n "
|
186
|
+
end
|
187
|
+
|
188
|
+
it "each_line" do
|
189
|
+
f1 = test_frame
|
190
|
+
f1.each_line.collect{|a|a}.should == [
|
191
|
+
["1234", [7, 7, 7, 7], [0, 0, 0, 0]],
|
192
|
+
["2345", [7, 7, 7, 7], [0, 0, 0, 0]],
|
193
|
+
["3456", [7, 7, 7, 7], [0, 0, 0, 0]],
|
194
|
+
["4567", [7, 7, 7, 7], [0, 0, 0, 0]]
|
195
|
+
]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "fg_buffer=" do
|
199
|
+
f1 = test_frame
|
200
|
+
f1.fg_buffer = [[8],[6,7,8]]
|
201
|
+
f1.fg_buffer.should == [[8, 7, 7, 7], [6, 7, 8, 7], [7, 7, 7, 7], [7, 7, 7, 7]]
|
202
|
+
f1.bg_buffer.should == [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
203
|
+
end
|
204
|
+
|
205
|
+
it "bg_buffer=" do
|
206
|
+
f1 = test_frame
|
207
|
+
f1.bg_buffer = [[8],[6,7,8]]
|
208
|
+
f1.fg_buffer.should == [[7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7]]
|
209
|
+
f1.bg_buffer.should == [[8, 0, 0, 0], [6, 7, 8, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
210
|
+
end
|
211
|
+
|
212
|
+
it "normalize range" do
|
213
|
+
f1 = buffer(size = point(2,4))
|
214
|
+
f1.fill bg:255
|
215
|
+
f1.bg_buffer.should == [[255,255],[255,255],[255,255],[255,255]]
|
216
|
+
f1.normalize 1..2
|
217
|
+
f1.bg_buffer.should == [[255,255],[255,255],[255,255],[255,255]]
|
218
|
+
f1.normalize 1...2
|
219
|
+
f1.bg_buffer.should == [[255,255],[255,255],[255,255],[255,255]]
|
220
|
+
f1.size.should == size
|
221
|
+
f1.contents.length.should == size.y
|
222
|
+
f1.fg_buffer.length.should == size.y
|
223
|
+
f1.bg_buffer.length.should == size.y
|
224
|
+
end
|
169
225
|
end
|
170
226
|
end
|
data/spec/color_spec.rb
CHANGED
@@ -32,5 +32,19 @@ describe "Color" do
|
|
32
32
|
color("#abc").to_hex.should == "#aabbcc"
|
33
33
|
color("#abcdef").to_hex.should == "#abcdef"
|
34
34
|
end
|
35
|
+
|
36
|
+
it "br" do
|
37
|
+
color("#fff").br.should == 1.0
|
38
|
+
color("#000").br.should == 0.0
|
39
|
+
(color("#ff7f00").br*100).to_i.should == 49
|
40
|
+
end
|
41
|
+
|
42
|
+
it "to_screen_color" do
|
43
|
+
color("#ff0").to_screen_color.should == 226
|
44
|
+
color("#011").to_screen_color.should == 16
|
45
|
+
color("#777").to_screen_color.should == 243
|
46
|
+
color("#000").to_screen_color.should == 0
|
47
|
+
color("#ffffff").to_screen_color.should == 15
|
48
|
+
end
|
35
49
|
end
|
36
50
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module WindowBlessing
|
4
|
+
describe "EventManager" do
|
5
|
+
include Tools
|
6
|
+
|
7
|
+
it "inspect" do
|
8
|
+
em = EventManager.new "a parent"
|
9
|
+
em.inspect["EventManager"].should == "EventManager"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "custom event" do
|
13
|
+
em = EventManager.new "a parent"
|
14
|
+
val = 0
|
15
|
+
em.on(:custom_event) {|event|val = event[:val]}
|
16
|
+
val.should == 0
|
17
|
+
em.handle_event type: :custom_event, :val => 1
|
18
|
+
val.should == 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it "on_event_exception" do
|
22
|
+
em = EventManager.new "a parent"
|
23
|
+
exception_count = 0
|
24
|
+
em.on(:event_exception) {exception_count+=1}
|
25
|
+
em.on(:custom_event) {raise "foo"}
|
26
|
+
em.handle_event type: :custom_event
|
27
|
+
exception_count.should == 1
|
28
|
+
end
|
29
|
+
|
30
|
+
it "on_every_event" do
|
31
|
+
em = EventManager.new "a parent"
|
32
|
+
event_count = 0
|
33
|
+
em.on {event_count+=1}
|
34
|
+
em.handle_event type: :custom_event
|
35
|
+
em.handle_event type: :a_different_custom_event
|
36
|
+
event_count.should == 2
|
37
|
+
end
|
38
|
+
|
39
|
+
it "on_unhandled_event" do
|
40
|
+
em = EventManager.new "a parent"
|
41
|
+
handled = ""
|
42
|
+
|
43
|
+
em.on(:custom_event) {handled+="a"}
|
44
|
+
em.on(:unhandled_event) {handled+="b"}
|
45
|
+
|
46
|
+
em.handle_event type: :custom_event
|
47
|
+
em.handle_event type: :a_different_custom_event
|
48
|
+
em.handle_event type: :b_different_custom_event
|
49
|
+
em.handle_event type: :custom_event
|
50
|
+
handled.should == "abba"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "exception in on_event_exception handler" do
|
54
|
+
em = EventManager.new "a parent"
|
55
|
+
handled = ""
|
56
|
+
|
57
|
+
em.on(:event_exception) {handled+="e";raise "foo"}
|
58
|
+
em.on(:custom_event) {handled+="c";raise "foo"}
|
59
|
+
|
60
|
+
em.handle_event type: :custom_event
|
61
|
+
handled.should == "ce"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "on_last" do
|
65
|
+
em = EventManager.new "a parent"
|
66
|
+
handled = ""
|
67
|
+
|
68
|
+
em.on(:custom_event) {handled += "a"}
|
69
|
+
em.on(:custom_event) {handled += "b"}
|
70
|
+
em.on_last(:custom_event) {handled += "!"}
|
71
|
+
|
72
|
+
em.handle_event type: :custom_event
|
73
|
+
handled.should == "ba!"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "handle_events" do
|
77
|
+
em = EventManager.new "a parent"
|
78
|
+
handled = ""
|
79
|
+
em.on(:custom_event) {handled += "a"}
|
80
|
+
em.handle_events [{type: :custom_event},{type: :other_custom_event},{type: :custom_event}]
|
81
|
+
handled.should == "aa"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "layered event types" do
|
85
|
+
em = EventManager.new "a parent"
|
86
|
+
handled = ""
|
87
|
+
em.on(:custom_event) {handled += "C"}
|
88
|
+
em.on(:custom_event, :sub_type_a) {handled += "ca"}
|
89
|
+
em.on(:custom_event, :sub_type_b) {handled += "cb"}
|
90
|
+
|
91
|
+
em.handle_event :type => :custom_event
|
92
|
+
handled.should == "C"
|
93
|
+
|
94
|
+
handled = ""
|
95
|
+
em.handle_event :type => [:custom_event]
|
96
|
+
handled.should == "C"
|
97
|
+
|
98
|
+
handled = ""
|
99
|
+
em.handle_event :type => [:custom_event, :sub_type_a]
|
100
|
+
handled.should == "caC"
|
101
|
+
|
102
|
+
handled = ""
|
103
|
+
em.handle_event :type => [:custom_event, :sub_type_b]
|
104
|
+
handled.should == "cbC"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|