window_blessing 0.0.1 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|